forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/14.0'
Change-Id: Ia809bda892afe5321aaaca2275f24baaf9569abc
This commit is contained in:
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
BIN
doc/qtcreator/images/qtcreator-projects-cpp-code-model.webp
Normal file
BIN
doc/qtcreator/images/qtcreator-projects-cpp-code-model.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
@@ -23,7 +23,9 @@
|
||||
applications on them.
|
||||
|
||||
\note If you use qmake to build the project and the device does not have
|
||||
Qt libraries, you need a fake Qt installation.
|
||||
Qt libraries, you need a Qt installation that meets the requirements in
|
||||
\l{Self-built Qt versions}. In addition, the \c mkspecs directory needs
|
||||
to be complete enough to parse .pro files.
|
||||
|
||||
The following toolchains are supported for building applications:
|
||||
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
You are advised to use CMake to build applications in the Docker container.
|
||||
|
||||
\note Enable the Docker plugin to use it.
|
||||
|
||||
To pull images from Docker hub or other registries, use the
|
||||
\l{https://docs.docker.com/engine/reference/commandline/pull/}{docker pull}
|
||||
command.
|
||||
@@ -64,7 +66,8 @@
|
||||
Go to \preferences > \uicontrol Kits to check
|
||||
that the automatically generated kits point to the appropriate kit items.
|
||||
|
||||
\sa {Docker}{How To: Develop for Docker}, {Manage Kits}{How To: Manage Kits}
|
||||
\sa {Enable and disable plugins}, {Docker}{How To: Develop for Docker},
|
||||
{Manage Kits}{How To: Manage Kits}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -75,6 +78,8 @@
|
||||
|
||||
\title Set preferences for Docker devices
|
||||
|
||||
\note Enable the Docker plugin to use it.
|
||||
|
||||
To set preferences for Docker devices:
|
||||
|
||||
\list 1
|
||||
@@ -165,7 +170,8 @@
|
||||
\uicontrol {List Auto-Detected Kit Items}. To remove
|
||||
them, select \uicontrol {Remove Auto-Detected Kit Items}.
|
||||
|
||||
\sa {Docker}{How To: Develop for Docker}, {Manage Kits}{How To: Manage Kits}
|
||||
\sa {Enable and disable plugins}, {Docker}{How To: Develop for Docker},
|
||||
{Manage Kits}{How To: Manage Kits}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -176,6 +182,8 @@
|
||||
|
||||
\title Build for and run on Docker devices
|
||||
|
||||
\note Enable the Docker plugin to use it.
|
||||
|
||||
To specify build settings for Docker images:
|
||||
|
||||
\list 1
|
||||
@@ -188,5 +196,6 @@
|
||||
Select \uicontrol Run to specify run settings. Usually, you can use
|
||||
the default settings.
|
||||
|
||||
\sa {Docker}{How To: Develop for Docker}, {Manage Kits}{How To: Manage Kits}
|
||||
\sa {Enable and disable plugins}, {Docker}{How To: Develop for Docker},
|
||||
{Manage Kits}{How To: Manage Kits}
|
||||
*/
|
||||
|
@@ -124,8 +124,34 @@
|
||||
The document outline in the \l{Outline} view is backed by clangd's document
|
||||
symbol support, which makes the results more reliable than before.
|
||||
|
||||
\sa {Code Model}, {Clangd}, {Specify clangd settings},
|
||||
{Specify Clang tools settings}, {Use compilation databases}
|
||||
\sa {Configure C++ code model}, {Specify clangd settings},
|
||||
{Specify Clang tools settings}, {Use compilation databases},
|
||||
{Code Model}, {Clangd}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page creator-how-to-cpp-code-model.html
|
||||
\previouspage creator-how-tos.html
|
||||
|
||||
\ingroup creator-how-to-configure-editors
|
||||
\ingroup creator-how-to-projects-configure
|
||||
|
||||
\title Configure C++ code model
|
||||
|
||||
The code model offers services such as code completion, syntactic and
|
||||
semantic highlighting, and diagnostics.
|
||||
|
||||
To configure the C++ code model for a project:
|
||||
|
||||
\list 1
|
||||
\li Go to \uicontrol Projects > \uicontrol {Project Settings} >
|
||||
\uicontrol {C++ Code Model}.
|
||||
\image qtcreator-projects-cpp-code-model.webp {C++ Code Model settings}
|
||||
\li Clear \uicontrol {Use global settings}.
|
||||
\li Set \uicontrol {C++ Code Model} settings for the project.
|
||||
\endlist
|
||||
|
||||
\sa {Code Model}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -138,40 +164,43 @@
|
||||
|
||||
\brief Sets global preferences for the code model.
|
||||
|
||||
The Clang code model offers services such as code completion, syntactic and
|
||||
The code model offers services such as code completion, syntactic and
|
||||
semantic highlighting, and diagnostics.
|
||||
|
||||
To configure the Clang code model globally:
|
||||
To configure the C++ code model globally, go to \preferences >
|
||||
\uicontrol C++ > \uicontrol {Code Model}.
|
||||
|
||||
\list 1
|
||||
\image qtcreator-preferences-code-model.webp {C++ Code Model preferences}
|
||||
|
||||
\li Select \preferences > \uicontrol C++ >
|
||||
\uicontrol {Code Model}.
|
||||
|
||||
\image qtcreator-preferences-code-model.webp {C++ Code Model preferences}
|
||||
|
||||
\li To instruct the code model to interpret ambiguous header files as C
|
||||
language files if you develop mainly using C, select the
|
||||
\uicontrol {Interpret ambiguous headers as C headers} check box.
|
||||
|
||||
\li To process precompiled headers, deselect the
|
||||
\uicontrol {Ignore precompiled headers} check box.
|
||||
|
||||
\li To use the built-in preprocessor to show the
|
||||
pre-processed source file in the editor, select
|
||||
\uicontrol {Use built-in preprocessor to show pre-processed files}.
|
||||
The following table summarizes the preferences.
|
||||
|
||||
\table
|
||||
\header
|
||||
\li Setting
|
||||
\li Value
|
||||
\row
|
||||
\li \uicontrol {Interpret ambiguous headers as C headers}
|
||||
\li Instructs the code model to interpret ambiguous header files as C
|
||||
language files. Select this checkbox if you develop mainly using C.
|
||||
\row
|
||||
\li \uicontrol {Ignore precompiled headers}
|
||||
\li Clear this checkbox to process precompiled headers.
|
||||
\row
|
||||
\li \uicontrol {Use built-in preprocessor to show pre-processed files}
|
||||
\li Uses the built-in preprocessor to show the
|
||||
pre-processed source file in the editor.
|
||||
\row
|
||||
\li \uicontrol {Do not index files greater than}
|
||||
\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
|
||||
files to index is limited to 5MB by default. To adjust the limit,
|
||||
edit the value for the \uicontrol {Do not index files greater than}
|
||||
check box. To index all files, deselect the check box.
|
||||
files to index is limited to 5MB by default.
|
||||
|
||||
\li To ignore files that match wildcard patterns, select the
|
||||
\uicontrol {Ignore files} check box and enter each wildcard pattern
|
||||
on a separate line in the field.
|
||||
|
||||
\endlist
|
||||
To index all files, clear the checkbox.
|
||||
\row
|
||||
\li \uicontrol {Ignore files}
|
||||
\li To ignore files that match wildcard patterns, enter each wildcard
|
||||
pattern on a separate line in the field.
|
||||
\endtable
|
||||
|
||||
\section1 Inspect preprocessed C++ code
|
||||
|
||||
@@ -186,7 +215,8 @@
|
||||
this action also expands all \c {"#include <foo.h>"} statements to their
|
||||
actual contents.
|
||||
|
||||
\sa {Specify clangd settings}, {Clang Code Model}, {Clangd}
|
||||
\sa {Configure C++ code model}, {Specify clangd settings},
|
||||
{Clang Code Model}, {Clangd}
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@@ -108,28 +108,45 @@
|
||||
|
||||
To verify the installation of a particular Qt version, \QC
|
||||
calls \c {qmake -query} and checks that the directories referenced in the
|
||||
output exist. When \QC complains about the installation of a self-built Qt
|
||||
version, try running \c {make install} in the build directory to actually
|
||||
install Qt into the configured location. If you installed Qt using the Qt
|
||||
Installer, run \QMT to check for updates or to reinstall
|
||||
the Qt version.
|
||||
output exist. If you installed Qt using \QOI, run
|
||||
\QMT to check for updates or to reinstall the Qt version.
|
||||
|
||||
\section1 Minimum requirements
|
||||
If your build of Qt is incomplete but you still want to use qmake as build
|
||||
system, you need to ensure the following minimum requirements to use that
|
||||
setup with \QC.
|
||||
\section2 Self-built Qt versions
|
||||
|
||||
\list 1
|
||||
To build projects with a self-built Qt version, add it as described in
|
||||
\l{Set up new Qt versions}.
|
||||
|
||||
Your Qt has to meet the following minimum requirements:
|
||||
|
||||
\list
|
||||
\li qmake is an executable that understands the \c -query command-line
|
||||
argument.
|
||||
\li The \c bin and \c include directories have to exist. \QC fetches
|
||||
these directories by running \c{qmake -query}.
|
||||
\li The \c mkspecs directory should be complete enough to parse .pro
|
||||
files.
|
||||
\endlist
|
||||
|
||||
If your Qt version has no \c libQtCore.so, \QC cannot detect the ABI.
|
||||
Add a kit for the Qt version and configure it for CMake.
|
||||
|
||||
\sa {kits-tab}{Kits}
|
||||
\QC issues warnings if:
|
||||
|
||||
\list
|
||||
\li \c libQtCore.so is missing, so \QC cannot detect the ABI.
|
||||
\li \c toolchain.cmake is missing. For example, you built Qt with the
|
||||
\c -static option for an x86 platform.
|
||||
\endlist
|
||||
|
||||
Try the following:
|
||||
|
||||
\list
|
||||
\li Run \c {make install} in the build directory to install Qt into the
|
||||
configured location.
|
||||
\li Set the value of the \c CMAKE_PREFIX_PATH variable in \preferences >
|
||||
\uicontrol Kits > \uicontrol Kits > \uicontrol {CMake Configuration}
|
||||
to the location where you installed Qt.
|
||||
\endlist
|
||||
|
||||
\image qtcreator-edit-cmake-configuration-self-built-qt.webp {Setting the path to a self-built Qt}
|
||||
|
||||
\sa {Manage Kits}{How To: Manage Kits}, {kits-tab}{Kits}
|
||||
*/
|
||||
|
||||
|
@@ -85,6 +85,7 @@
|
||||
\li \l{Specify clangd settings}{Clangd}
|
||||
\li \l{Specify Clang tools settings}{Clang Tools}
|
||||
\li \l{Set Copilot preferences}{Copilot}
|
||||
\li \l{Configure C++ code model}{C++ Code Model}
|
||||
\li \l{Specify code style}{C++ Code Style}
|
||||
\li \l{Set C++ file naming preferences}{C++ File Naming}
|
||||
\li \l{Specify dependencies}{Dependencies}
|
||||
|
@@ -12,6 +12,7 @@ Product {
|
||||
property string versionTag: qtc.qtcreator_version.replace(/\.|-/g, "")
|
||||
|
||||
Qt.core.qdocEnvironment: [
|
||||
"GENERATED_ATTRIBUTIONS_DIR=" + product.buildDirectory,
|
||||
"IDE_DISPLAY_NAME=" + qtc.ide_display_name,
|
||||
"IDE_CASED_ID=" + qtc.ide_cased_id,
|
||||
"IDE_ID=" + qtc.ide_id,
|
||||
|
@@ -76,7 +76,9 @@ class Dumper(DumperBase):
|
||||
self.outputLock = threading.Lock()
|
||||
self.isCdb = True
|
||||
|
||||
#FIXME
|
||||
#FIXME
|
||||
def register_known_qt_types(self):
|
||||
DumperBase.register_known_qt_types(self)
|
||||
typeid = self.typeid_for_string('@QVariantMap')
|
||||
del self.type_code_cache[typeid]
|
||||
del self.type_target_cache[typeid]
|
||||
|
@@ -172,8 +172,6 @@ class DumperBase():
|
||||
self.qtCustomEventFunc = 0
|
||||
self.qtCustomEventPltFunc = 0
|
||||
self.qtPropertyFunc = 0
|
||||
self.qtversion = None
|
||||
self.qtns = None
|
||||
self.passExceptions = False
|
||||
self.isTesting = False
|
||||
self.qtLoaded = False
|
||||
@@ -189,6 +187,11 @@ class DumperBase():
|
||||
|
||||
self.dumpermodules = []
|
||||
|
||||
# These are sticky for the session
|
||||
self.qtversion = None
|
||||
self.qtversionAtLeast6 = None
|
||||
self.qtnamespace = None
|
||||
|
||||
self.init_type_cache()
|
||||
|
||||
try:
|
||||
@@ -211,7 +214,7 @@ class DumperBase():
|
||||
self.currentPrintsAddress = True
|
||||
self.currentChildType = None
|
||||
self.currentChildNumChild = None
|
||||
self.register_known_types()
|
||||
self.register_known_simple_types()
|
||||
|
||||
def setVariableFetchingOptions(self, args):
|
||||
self.last_args = args
|
||||
@@ -233,9 +236,16 @@ class DumperBase():
|
||||
self.useTimeStamps = int(args.get('timestamps', '0'))
|
||||
self.partialVariable = args.get('partialvar', '')
|
||||
self.uninitialized = args.get('uninitialized', [])
|
||||
self.qtversion = args.get('qtversion', 0x060602)
|
||||
self.qtnamespace = args.get('qtnamespace', '')
|
||||
|
||||
self.uninitialized = list(map(lambda x: self.hexdecode(x), self.uninitialized))
|
||||
|
||||
if self.qtversion is None:
|
||||
self.qtversion = args.get('qtversion', None)
|
||||
if self.qtversion == 0:
|
||||
self.qtversion = None
|
||||
if self.qtnamespace is None:
|
||||
self.qtnamespace = args.get('qtnamespace', None)
|
||||
|
||||
#self.warn('NAMESPACE: "%s"' % self.qtNamespace())
|
||||
#self.warn('EXPANDED INAMES: %s' % self.expandedINames)
|
||||
#self.warn('WATCHERS: %s' % self.watchers)
|
||||
@@ -256,11 +266,50 @@ class DumperBase():
|
||||
args['partialvar'] = ''
|
||||
self.fetchVariables(args)
|
||||
|
||||
def extractQtVersion(self):
|
||||
# can be overridden in bridges
|
||||
pass
|
||||
|
||||
def qtVersion(self):
|
||||
return self.qtversion
|
||||
if self.qtversion:
|
||||
return self.qtversion
|
||||
|
||||
#self.warn("ACCESSING UNKNOWN QT VERSION")
|
||||
self.qtversion = self.extractQtVersion()
|
||||
if self.qtversion:
|
||||
return self.qtversion
|
||||
|
||||
#self.warn("EXTRACTING QT VERSION FAILED. GUESSING NOW.")
|
||||
if self.qtversionAtLeast6 is None or self.qtversionAtLeast6 is True:
|
||||
return 0x060602
|
||||
return 0x050f00
|
||||
|
||||
def qtVersionAtLeast(self, version):
|
||||
# A hack to cover most of the changes from Qt 5 to 6
|
||||
if version == 0x60000 and self.qtversionAtLeast6 is not None:
|
||||
return self.qtversionAtLeast6
|
||||
if version == 0x50000: # FIXME: This drops unknown 4.x for now
|
||||
return True
|
||||
return self.qtVersion() >= version
|
||||
|
||||
def qtVersionPing(self, typeid, size_for_qt5=-1):
|
||||
# To be called from places where the type size is sufficient
|
||||
# to distinguish Qt 5.x and 6.x
|
||||
if size_for_qt5 == -1:
|
||||
size_for_qt5 = self.ptrSize()
|
||||
test_size = self.type_size(typeid)
|
||||
self.setQtVersionAtLeast6(test_size > size_for_qt5)
|
||||
|
||||
def setQtVersionAtLeast6(self, is6):
|
||||
if self.qtversionAtLeast6 is None:
|
||||
#self.warn("SETTING Qt VERSION AT LEAST 6 TO %s" % is6)
|
||||
self.qtversionAtLeast6 = is6
|
||||
self.register_known_qt_types()
|
||||
#else:
|
||||
# self.warn("QT VERSION ALREADY KNOWN")
|
||||
|
||||
def qtNamespace(self):
|
||||
return self.qtnamespace
|
||||
return '' if self.qtnamespace is None else self.qtnamespace
|
||||
|
||||
def resetPerStepCaches(self):
|
||||
self.perStepCache = {}
|
||||
@@ -494,8 +543,13 @@ class DumperBase():
|
||||
def register_struct(self, name, p5=0, p6=0, s=0, qobject_based=False):
|
||||
# p5 = n -> n * ptrsize for Qt 5
|
||||
# p6 = n -> n * ptrsize for Qt 6
|
||||
#if self.qtVersion() >= 0x060000: # FIXME: Qt 5, ptrSize()
|
||||
size = 8 * p6 + s
|
||||
if self.qtversionAtLeast6 is None:
|
||||
self.warn("TOO EARLY TO GUESS QT VERSION")
|
||||
size = 8 * p6 + s
|
||||
elif self.qtversionAtLeast6 is True:
|
||||
size = 8 * p6 + s
|
||||
else:
|
||||
size = 8 * p5 + s
|
||||
typeid = self.typeid_for_string(name)
|
||||
self.type_code_cache[typeid] = TypeCode.Struct
|
||||
self.type_size_cache[typeid] = size
|
||||
@@ -503,7 +557,7 @@ class DumperBase():
|
||||
self.type_alignment_cache[typeid] = 8
|
||||
return typeid
|
||||
|
||||
def register_known_types(self):
|
||||
def register_known_simple_types(self):
|
||||
typeid = 0
|
||||
self.typeid_cache[''] = typeid
|
||||
self.type_code_cache[typeid] = TypeCode.Void
|
||||
@@ -563,6 +617,8 @@ class DumperBase():
|
||||
|
||||
self.register_enum('@Qt::ItemDataRole', 4)
|
||||
|
||||
def register_known_qt_types(self):
|
||||
#self.warn("REGISTERING KNOWN QT TYPES NOW")
|
||||
self.register_struct('@QObject', p5=2, p6=2, qobject_based=True)
|
||||
self.register_struct('@QObjectPrivate', p5=10, p6=10) # FIXME: Not exact
|
||||
|
||||
@@ -680,9 +736,6 @@ class DumperBase():
|
||||
# Hex decoding operating on str, return str.
|
||||
@staticmethod
|
||||
def hexdecode(s, encoding='utf8'):
|
||||
if sys.version_info[0] == 2:
|
||||
# For python2 we need an extra str() call to return str instead of unicode
|
||||
return str(s.decode('hex').decode(encoding))
|
||||
return bytes.fromhex(s).decode(encoding)
|
||||
|
||||
# Hex encoding operating on str or bytes, return str.
|
||||
@@ -690,10 +743,6 @@ class DumperBase():
|
||||
def hexencode(s):
|
||||
if s is None:
|
||||
s = ''
|
||||
if sys.version_info[0] == 2:
|
||||
if isinstance(s, buffer):
|
||||
return bytes(s).encode('hex')
|
||||
return s.encode('hex')
|
||||
if isinstance(s, str):
|
||||
s = s.encode('utf8')
|
||||
return hexencode_(s)
|
||||
@@ -711,9 +760,9 @@ class DumperBase():
|
||||
return limit
|
||||
|
||||
def vectorData(self, value):
|
||||
if self.qtVersion() >= 0x060000:
|
||||
if self.qtVersionAtLeast(0x060000):
|
||||
data, length, alloc = self.qArrayData(value)
|
||||
elif self.qtVersion() >= 0x050000:
|
||||
elif self.qtVersionAtLeast(0x050000):
|
||||
vector_data_ptr = self.extractPointer(value)
|
||||
if self.ptrSize() == 4:
|
||||
(ref, length, alloc, offset) = self.split('IIIp', vector_data_ptr)
|
||||
@@ -729,7 +778,7 @@ class DumperBase():
|
||||
return data, length
|
||||
|
||||
def qArrayData(self, value):
|
||||
if self.qtVersion() >= 0x60000:
|
||||
if self.qtVersionAtLeast(0x60000):
|
||||
dd, data, length = self.split('ppp', value)
|
||||
if dd:
|
||||
_, _, alloc = self.split('iip', dd)
|
||||
@@ -740,7 +789,7 @@ class DumperBase():
|
||||
|
||||
def qArrayDataHelper(self, array_data_ptr):
|
||||
# array_data_ptr is what is e.g. stored in a QByteArray's d_ptr.
|
||||
if self.qtVersion() >= 0x050000:
|
||||
if self.qtVersionAtLeast(0x050000):
|
||||
# QTypedArray:
|
||||
# - QtPrivate::RefCount ref
|
||||
# - int length
|
||||
@@ -753,7 +802,7 @@ class DumperBase():
|
||||
data = data & 0xffffffff
|
||||
else:
|
||||
data = data & 0xffffffffffffffff
|
||||
elif self.qtVersion() >= 0x040000:
|
||||
elif self.qtVersionAtLeast(0x040000):
|
||||
# Data:
|
||||
# - QBasicAtomicInt ref;
|
||||
# - int alloc, length;
|
||||
@@ -1597,7 +1646,7 @@ class DumperBase():
|
||||
|
||||
intSize = 4
|
||||
ptrSize = self.ptrSize()
|
||||
if self.qtVersion() >= 0x060000:
|
||||
if self.qtVersionAtLeast(0x060000):
|
||||
# Size of QObjectData: 9 pointer + 2 int
|
||||
# - vtable
|
||||
# - QObject *q_ptr;
|
||||
@@ -1618,7 +1667,7 @@ class DumperBase():
|
||||
# - QList<QPointer<QObject> > eventFilters;
|
||||
# - QString objectName
|
||||
objectNameAddress = extra + 12 * ptrSize
|
||||
elif self.qtVersion() >= 0x050000:
|
||||
elif self.qtVersionAtLeast(0x050000):
|
||||
# Size of QObjectData: 5 pointer + 2 int
|
||||
# - vtable
|
||||
# - QObject *q_ptr;
|
||||
@@ -1811,7 +1860,7 @@ class DumperBase():
|
||||
# a Q_OBJECT SMO has a non-null superdata (unless it's QObject itself),
|
||||
# a Q_GADGET SMO has a null superdata (hopefully)
|
||||
if result and not isQObjectProper:
|
||||
if self.qtVersion() >= 0x60000 and self.isWindowsTarget():
|
||||
if self.qtVersionAtLeast(0x60000) and self.isWindowsTarget():
|
||||
(direct, indirect) = self.split('pp', result)
|
||||
# since Qt 6 there is an additional indirect super data getter on windows
|
||||
if direct == 0 and indirect == 0:
|
||||
@@ -1895,14 +1944,14 @@ class DumperBase():
|
||||
return result
|
||||
|
||||
def listData(self, value, check=True):
|
||||
if self.qtVersion() >= 0x60000:
|
||||
if self.qtVersionAtLeast(0x60000):
|
||||
dd, data, size = self.split('ppi', value)
|
||||
return data, size
|
||||
|
||||
base = self.extractPointer(value)
|
||||
(ref, alloc, begin, end) = self.split('IIII', base)
|
||||
array = base + 16
|
||||
if self.qtVersion() < 0x50000:
|
||||
if not self.qtVersionAtLeast(0x50000):
|
||||
array += self.ptrSize()
|
||||
size = end - begin
|
||||
|
||||
@@ -1941,7 +1990,7 @@ class DumperBase():
|
||||
def metaString(self, metaObjectPtr, index, revision):
|
||||
ptrSize = self.ptrSize()
|
||||
stringdataOffset = ptrSize
|
||||
if self.isWindowsTarget() and self.qtVersion() >= 0x060000:
|
||||
if self.isWindowsTarget() and self.qtVersionAtLeast(0x060000):
|
||||
stringdataOffset += ptrSize # indirect super data member
|
||||
stringdata = self.extract_pointer_at_address(int(metaObjectPtr) + stringdataOffset)
|
||||
|
||||
@@ -1970,19 +2019,19 @@ class DumperBase():
|
||||
self.putField('sortgroup', sortorder)
|
||||
|
||||
def putQMetaStuff(self, value, origType):
|
||||
if self.qtVersion() >= 0x060000:
|
||||
if self.qtVersionAtLeast(0x060000):
|
||||
metaObjectPtr, handle = value.split('pp')
|
||||
else:
|
||||
metaObjectPtr, handle = value.split('pI')
|
||||
if metaObjectPtr != 0:
|
||||
if self.qtVersion() >= 0x060000:
|
||||
if self.qtVersionAtLeast(0x060000):
|
||||
if handle == 0:
|
||||
self.putEmptyValue()
|
||||
return
|
||||
revision = 9
|
||||
name, alias, flags, keyCount, data = self.split('IIIII', handle)
|
||||
index = name
|
||||
elif self.qtVersion() >= 0x050000:
|
||||
elif self.qtVersionAtLeast(0x050000):
|
||||
revision = 7
|
||||
dataPtr = self.extract_pointer_at_address(metaObjectPtr + 2 * self.ptrSize())
|
||||
index = self.extractInt(dataPtr + 4 * handle)
|
||||
@@ -2024,7 +2073,7 @@ class DumperBase():
|
||||
|
||||
def extractDataPtr(someMetaObjectPtr):
|
||||
# dataPtr = metaObjectPtr['d']['data']
|
||||
if self.qtVersion() >= 0x60000 and self.isWindowsTarget():
|
||||
if self.qtVersionAtLeast(0x60000) and self.isWindowsTarget():
|
||||
offset = 3
|
||||
else:
|
||||
offset = 2
|
||||
@@ -2054,13 +2103,13 @@ class DumperBase():
|
||||
extraData = 0
|
||||
if qobjectPtr:
|
||||
dd = self.extract_pointer_at_address(qobjectPtr + ptrSize)
|
||||
if self.qtVersion() >= 0x60000:
|
||||
if self.qtVersionAtLeast(0x60000):
|
||||
(dvtablePtr, qptr, parent, children, bindingStorageData, bindingStatus,
|
||||
flags, postedEvents, dynMetaObjectPtr, # Up to here QObjectData.
|
||||
extraData, threadDataPtr, connectionListsPtr,
|
||||
sendersPtr, currentSenderPtr) \
|
||||
= self.split('pp{@QObject*}{@QList<@QObject *>}ppIIp' + 'ppppp', dd)
|
||||
elif self.qtVersion() >= 0x50000:
|
||||
elif self.qtVersionAtLeast(0x50000):
|
||||
(dvtablePtr, qptr, parent, children, flags, postedEvents,
|
||||
dynMetaObjectPtr, # Up to here QObjectData.
|
||||
extraData, threadDataPtr, connectionListsPtr,
|
||||
@@ -2186,7 +2235,7 @@ typename))
|
||||
with Children(self):
|
||||
# Static properties.
|
||||
for i in range(propertyCount):
|
||||
if self.qtVersion() >= 0x60000:
|
||||
if self.qtVersionAtLeast(0x60000):
|
||||
t = self.split('IIIII', dataPtr + properties * 4 + 20 * i)
|
||||
else:
|
||||
t = self.split('III', dataPtr + properties * 4 + 12 * i)
|
||||
@@ -2239,18 +2288,18 @@ typename))
|
||||
data += inner_size
|
||||
|
||||
variant_typeid = self.cheap_typeid_from_name('@QVariant')
|
||||
if self.qtVersion() >= 0x60000:
|
||||
if self.qtVersionAtLeast(0x60000):
|
||||
values = vectorGenerator(extraData + 3 * ptrSize, variant_typeid)
|
||||
elif self.qtVersion() >= 0x50600:
|
||||
elif self.qtVersionAtLeast(0x50600):
|
||||
values = vectorGenerator(extraData + 2 * ptrSize, variant_typeid)
|
||||
elif self.qtVersion() >= 0x50000:
|
||||
elif self.qtVersionAtLeast(0x50000):
|
||||
values = list5Generator(extraData + 2 * ptrSize, variant_typeid)
|
||||
else:
|
||||
variantptr_typeid = self.cheap_typeid_from_name('@QVariant')
|
||||
values = list5Generator(extraData + 2 * ptrSize, variantptr_typeid)
|
||||
|
||||
bytearray_typeid = self.cheap_typeid_from_name('@QByteArray')
|
||||
if self.qtVersion() >= 0x60000:
|
||||
if self.qtVersionAtLeast(0x60000):
|
||||
names = list6Generator(extraData, bytearray_typeid)
|
||||
else:
|
||||
names = list5Generator(extraData + ptrSize, bytearray_typeid)
|
||||
@@ -2671,10 +2720,7 @@ typename))
|
||||
try:
|
||||
if funcname.startswith('qdump__'):
|
||||
typename = funcname[7:]
|
||||
if sys.version_info > (3,):
|
||||
spec = inspect.getfullargspec(function)
|
||||
else:
|
||||
spec = inspect.getargspec(function)
|
||||
spec = inspect.getfullargspec(function)
|
||||
if len(spec.args) == 2:
|
||||
self.qqDumpers[typename] = function
|
||||
elif len(spec.args) == 3 and len(spec.defaults) == 1:
|
||||
@@ -2721,11 +2767,8 @@ typename))
|
||||
def reloadDumpers(self, args):
|
||||
for mod in self.dumpermodules:
|
||||
m = sys.modules[mod]
|
||||
if sys.version_info[0] >= 3:
|
||||
import importlib
|
||||
importlib.reload(m)
|
||||
else:
|
||||
reload(m)
|
||||
import importlib
|
||||
importlib.reload(m)
|
||||
self.setupDumpers(args)
|
||||
|
||||
def loadDumpers(self, args):
|
||||
@@ -3427,9 +3470,9 @@ typename))
|
||||
):
|
||||
return True
|
||||
if strippedName == 'QStringList':
|
||||
return self.dumper.qtVersion() >= 0x050000
|
||||
return self.dumper.qtVersionAtLeast(0x050000)
|
||||
if strippedName == 'QList':
|
||||
return self.dumper.qtVersion() >= 0x050600
|
||||
return self.dumper.qtVersionAtLeast(0x050600)
|
||||
return False
|
||||
|
||||
class Field:
|
||||
@@ -3550,7 +3593,7 @@ typename))
|
||||
if typename.startswith('QList<') or typename.startswith('QVector<'):
|
||||
typeid = self.typeid_for_string(typename)
|
||||
if typeid:
|
||||
size = 3 * self.ptrSize() if self.qtVersion() >= 0x060000 else self.ptrSize()
|
||||
size = 3 * self.ptrSize() if self.qtVersionAtLeast(0x060000) else self.ptrSize()
|
||||
self.type_code_cache[typeid] = TypeCode.Struct
|
||||
self.type_size_cache[typeid] = size
|
||||
return typeid
|
||||
|
@@ -874,6 +874,36 @@ class Dumper(DumperBase):
|
||||
except:
|
||||
return '0x%x' % address
|
||||
|
||||
def qtVersionString(self):
|
||||
try:
|
||||
return str(gdb.lookup_symbol('qVersion')[0].value()())
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
ns = self.qtNamespace()
|
||||
return str(gdb.parse_and_eval("((const char*(*)())'%sqVersion')()" % ns))
|
||||
except:
|
||||
pass
|
||||
return None
|
||||
|
||||
def extractQtVersion(self):
|
||||
try:
|
||||
# Only available with Qt 5.3+
|
||||
return int(str(gdb.parse_and_eval('((void**)&qtHookData)[2]')), 16)
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
version = self.qtVersionString()
|
||||
(major, minor, patch) = version[version.find('"') + 1:version.rfind('"')].split('.')
|
||||
qtversion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch)
|
||||
self.qtVersion = lambda: qtversion
|
||||
return qtversion
|
||||
except:
|
||||
# Use fallback until we have a better answer.
|
||||
return None
|
||||
|
||||
|
||||
def createSpecialBreakpoints(self, args):
|
||||
self.specialBreakpoints = []
|
||||
|
||||
|
@@ -18,11 +18,7 @@ sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.curre
|
||||
|
||||
# Simplify development of this module by reloading deps
|
||||
if 'dumper' in sys.modules:
|
||||
if sys.version_info[0] >= 3:
|
||||
if sys.version_info[1] > 3:
|
||||
from importlib import reload
|
||||
else:
|
||||
def reload(m): print('Unsupported Python version - not reloading %s' % str(m))
|
||||
from importlib import reload
|
||||
reload(sys.modules['dumper'])
|
||||
|
||||
from dumper import DumperBase, SubItem, Children, TopLevelItem
|
||||
@@ -34,16 +30,10 @@ from dumper import DumperBase, SubItem, Children, TopLevelItem
|
||||
#######################################################################
|
||||
|
||||
qqWatchpointOffset = 10000
|
||||
_c_str_trans = None
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
_c_str_trans = str.maketrans({"\n": "\\n", '"':'\\"', "\\":"\\\\"})
|
||||
_c_str_trans = str.maketrans({"\n": "\\n", '"':'\\"', "\\":"\\\\"})
|
||||
|
||||
def toCString(s):
|
||||
if _c_str_trans is not None:
|
||||
return str(s).translate(_c_str_trans)
|
||||
else:
|
||||
return str(s).replace('\\', '\\\\').replace('\n', '\\n').replace('"', '\\"')
|
||||
return str(s).translate(_c_str_trans)
|
||||
|
||||
def fileNameAsString(file):
|
||||
return toCString(file) if file.IsValid() else ''
|
||||
@@ -783,6 +773,54 @@ class Dumper(DumperBase):
|
||||
|
||||
self.fetchInternalFunctions = lambda: None
|
||||
|
||||
def extractQtVersion(self):
|
||||
for func in self.target.FindFunctions('qVersion'):
|
||||
name = func.GetSymbol().GetName()
|
||||
if name == None:
|
||||
continue
|
||||
if name.endswith('()'):
|
||||
name = name[:-2]
|
||||
if name.count(':') > 2:
|
||||
continue
|
||||
|
||||
#qtNamespace = name[:name.find('qVersion')]
|
||||
#self.qtNamespace = lambda: qtNamespace
|
||||
|
||||
options = lldb.SBExpressionOptions()
|
||||
res = self.target.EvaluateExpression(name + '()', options)
|
||||
|
||||
if not res.IsValid() or not res.GetType().IsPointerType():
|
||||
exp = '((const char*())%s)()' % name
|
||||
res = self.target.EvaluateExpression(exp, options)
|
||||
|
||||
if not res.IsValid() or not res.GetType().IsPointerType():
|
||||
exp = '((const char*())_Z8qVersionv)()'
|
||||
res = self.target.EvaluateExpression(exp, options)
|
||||
|
||||
if not res.IsValid() or not res.GetType().IsPointerType():
|
||||
continue
|
||||
|
||||
version = str(res)
|
||||
if version.count('.') != 2:
|
||||
continue
|
||||
|
||||
version.replace("'", '"') # Both seem possible
|
||||
version = version[version.find('"') + 1:version.rfind('"')]
|
||||
|
||||
(major, minor, patch) = version.split('.')
|
||||
qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch)
|
||||
return qtVersion
|
||||
|
||||
try:
|
||||
versionValue = self.target.EvaluateExpression('qtHookData[2]').GetNonSyntheticValue()
|
||||
if versionValue.IsValid():
|
||||
return versionValue.unsigned
|
||||
except:
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def handleCommand(self, command):
|
||||
result = lldb.SBCommandReturnObject()
|
||||
self.debugger.GetCommandInterpreter().HandleCommand(command, result)
|
||||
@@ -2312,9 +2350,6 @@ class SummaryProvider(LogMixin):
|
||||
if encoding in text_encodings:
|
||||
try:
|
||||
decodedValue = Dumper.hexdecode(summaryValue, encoding)
|
||||
# LLDB expects UTF-8 for python 2
|
||||
if sys.version_info[0] < 3:
|
||||
return "\"%s\"" % (decodedValue.encode('utf8'))
|
||||
return '"' + decodedValue + '"'
|
||||
except:
|
||||
return "<failed to decode '%s' as '%s': %s>" % (summaryValue, encoding, sys.exc_info()[1])
|
||||
|
@@ -33,7 +33,8 @@ def qedit__QByteArray(d, value, data):
|
||||
|
||||
|
||||
def qdump__QByteArray(d, value):
|
||||
if d.qtVersion() >= 0x60000:
|
||||
d.qtVersionPing(value.typeid)
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
dd, data, length = value.split('ppi')
|
||||
if dd:
|
||||
_, _, alloc = d.split('iii', dd)
|
||||
@@ -76,7 +77,8 @@ def qdump__QByteArray(d, value):
|
||||
|
||||
|
||||
def qdump__QBitArray(d, value):
|
||||
if d.qtVersion() >= 0x60000:
|
||||
d.qtVersionPing(value.typeid)
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
_, data, basize = value.split('ppi')
|
||||
else:
|
||||
data, basize, _ = d.qArrayData(value['d'])
|
||||
@@ -232,13 +234,13 @@ def qdump__QStandardItem(d, value):
|
||||
#d.createType('@QStandardItem*')
|
||||
|
||||
vtable, dptr = value.split('pp')
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
model, parent, values, children, rows, cols, item = \
|
||||
d.split('pp{@QList<@QStandardItemData>}{@QList<@QStandardItem *>}IIp', dptr)
|
||||
else:
|
||||
# There used to be a virtual destructor that got removed in
|
||||
# 88b6abcebf29b455438 on Apr 18 17:01:22 2017
|
||||
if d.qtVersion() < 0x050900 and not d.isMsvcTarget():
|
||||
if not d.qtVersionAtLeast(0x050900) and not d.isMsvcTarget():
|
||||
dptr += d.ptrSize();
|
||||
model, parent, values, children, rows, cols, item = \
|
||||
d.split('pp{@QVector<@QStandardItemData>}{@QVector<@QStandardItem *>}IIp', dptr)
|
||||
@@ -266,7 +268,7 @@ def qdump__QDate(d, value):
|
||||
d.enumExpression('DateFormat', 'TextDate'))
|
||||
d.putCallItem('(ISO)', '@QString', value, 'toString',
|
||||
d.enumExpression('DateFormat', 'ISODate'))
|
||||
if d.qtVersion() < 0x060000:
|
||||
if not d.qtVersionAtLeast(0x060000):
|
||||
d.putCallItem('(SystemLocale)', '@QString', value, 'toString',
|
||||
d.enumExpression('DateFormat', 'SystemLocaleDate'))
|
||||
d.putCallItem('(Locale)', '@QString', value, 'toString',
|
||||
@@ -286,7 +288,7 @@ def qdump__QTime(d, value):
|
||||
d.enumExpression('DateFormat', 'TextDate'))
|
||||
d.putCallItem('(ISO)', '@QString', value, 'toString',
|
||||
d.enumExpression('DateFormat', 'ISODate'))
|
||||
if d.canCallLocale() and d.qtVersion() < 0x060000:
|
||||
if d.canCallLocale() and not d.qtVersionAtLeast(0x060000):
|
||||
d.putCallItem('(SystemLocale)', '@QString', value, 'toString',
|
||||
d.enumExpression('DateFormat', 'SystemLocaleDate'))
|
||||
d.putCallItem('(Locale)', '@QString', value, 'toString',
|
||||
@@ -305,13 +307,12 @@ def qdump__QTimeZone(d, value):
|
||||
|
||||
|
||||
def qdump__QDateTime(d, value):
|
||||
qtVersion = d.qtVersion()
|
||||
isValid = False
|
||||
# This relies on the Qt4/Qt5 internal structure layout:
|
||||
# {sharedref(4), ...
|
||||
base = d.extractPointer(value)
|
||||
is32bit = d.ptrSize() == 4
|
||||
if qtVersion >= 0x050200:
|
||||
if d.qtVersionAtLeast(0x050200):
|
||||
tiVersion = d.qtTypeInfoVersion()
|
||||
#DumperBase.warn('TI VERSION: %s' % tiVersion)
|
||||
if tiVersion is None:
|
||||
@@ -384,9 +385,9 @@ def qdump__QDateTime(d, value):
|
||||
# - [QTime time;]
|
||||
# - - uint mds;
|
||||
# - Spec spec;
|
||||
dateSize = 8 if qtVersion >= 0x050000 else 4 # Qt5: qint64, Qt4 uint
|
||||
dateSize = 8 if qtVersionAtLeast(0x050000) else 4 # Qt5: qint64, Qt4 uint
|
||||
# 4 byte padding after 4 byte QAtomicInt if we are on 64 bit and QDate is 64 bit
|
||||
refPlusPadding = 8 if qtVersion >= 0x050000 and d.ptrSize() == 8 else 4
|
||||
refPlusPadding = 8 if qtVersionAtLeast(0x050000) and d.ptrSize() == 8 else 4
|
||||
dateBase = base + refPlusPadding
|
||||
timeBase = dateBase + dateSize
|
||||
mds = d.extractInt(timeBase)
|
||||
@@ -410,7 +411,7 @@ def qdump__QDateTime(d, value):
|
||||
d.enumExpression('DateFormat', 'ISODate'))
|
||||
d.putCallItem('toUTC', '@QDateTime', value, 'toTimeSpec',
|
||||
d.enumExpression('TimeSpec', 'UTC'))
|
||||
if d.qtVersion() < 0x060000:
|
||||
if not d.qtVersionAtLeast(0x060000):
|
||||
d.putCallItem('(SystemLocale)', '@QString', value, 'toString',
|
||||
d.enumExpression('DateFormat', 'SystemLocaleDate'))
|
||||
d.putCallItem('(Locale)', '@QString', value, 'toString',
|
||||
@@ -756,7 +757,6 @@ def qdump__QFile(d, value):
|
||||
def qdump__QFileInfo(d, value):
|
||||
privAddress = d.extractPointer(value)
|
||||
#bit32 = d.ptrSize() == 4
|
||||
#qt5 = d.qtVersion() >= 0x050000
|
||||
#try:
|
||||
# d.putStringValue(value['d_ptr']['d'].dereference()['fileNames'][3])
|
||||
#except:
|
||||
@@ -876,7 +876,7 @@ def qdump__QVariantHash(d, value):
|
||||
|
||||
|
||||
def qdumpHelper_QHash(d, value, keyType, valueType):
|
||||
if d.qtVersion() >= 0x60000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
qdumpHelper_QHash_6(d, value, keyType, valueType)
|
||||
else:
|
||||
qdumpHelper_QHash_5(d, value, keyType, valueType)
|
||||
@@ -918,7 +918,7 @@ def qdumpHelper_QHash_5(d, value, keyType, valueType):
|
||||
|
||||
d.putItemCount(size)
|
||||
if d.isExpanded():
|
||||
isShort = d.qtVersion() < 0x050000 and keyType.name == 'int'
|
||||
isShort = not d.qtVersionAtLeast(0x050000) and keyType.name == 'int'
|
||||
with Children(d, size):
|
||||
node = hashDataFirstNode()
|
||||
for i in d.childRange():
|
||||
@@ -994,7 +994,7 @@ def qHashIteratorHelper(d, value):
|
||||
if d.isExpanded():
|
||||
with Children(d):
|
||||
node = d.extractPointer(value)
|
||||
isShort = d.qtVersion() < 0x050000 and keyType.name == 'int'
|
||||
isShort = not d.qtVersionAtLeast(0x050000) and keyType.name == 'int'
|
||||
if isShort:
|
||||
typeCode = 'P{%s}@{%s}' % (keyType.name, valueType.name)
|
||||
(pnext, key, padding2, val) = d.split(typeCode, node)
|
||||
@@ -1015,9 +1015,8 @@ def qdump__QHash__iterator(d, value):
|
||||
|
||||
def qdump__QHostAddress(d, value):
|
||||
dd = d.extractPointer(value)
|
||||
qtVersion = d.qtVersion()
|
||||
tiVersion = d.qtTypeInfoVersion()
|
||||
#DumperBase.warn('QT: %x, TI: %s' % (qtVersion, tiVersion))
|
||||
#DumperBase.warn('QT: %x, TI: %s' % (d.qtVersion(), tiVersion))
|
||||
mayNeedParse = True
|
||||
if tiVersion is not None:
|
||||
if tiVersion >= 16:
|
||||
@@ -1032,14 +1031,14 @@ def qdump__QHostAddress(d, value):
|
||||
else:
|
||||
(ipString, scopeId, a4, pad, a6, protocol, isParsed) \
|
||||
= d.split('{@QString}{@QString}{@quint32}I16sI{bool}', dd)
|
||||
elif qtVersion >= 0x050600: # 5.6.0 at f3aabb42
|
||||
elif qtVersionAtLeast(0x050600): # 5.6.0 at f3aabb42
|
||||
if d.ptrSize() == 8 or d.isWindowsTarget():
|
||||
(ipString, scopeId, a4, pad, a6, protocol, isParsed) \
|
||||
= d.split('{@QString}{@QString}{@quint32}I16sI{bool}', dd)
|
||||
else:
|
||||
(ipString, scopeId, a4, a6, protocol, isParsed) \
|
||||
= d.split('{@QString}{@QString}{@quint32}16sI{bool}', dd)
|
||||
elif qtVersion >= 0x050000: # 5.2.0 at 62feb088
|
||||
elif qtVersionAtLeast(0x050000): # 5.2.0 at 62feb088
|
||||
(ipString, scopeId, a4, a6, protocol, isParsed) \
|
||||
= d.split('{@QString}{@QString}{@quint32}16sI{bool}', dd)
|
||||
else: # 4.8.7 at b05d05f
|
||||
@@ -1104,7 +1103,8 @@ def qdumpHelper_QList(d, value, inner_typish):
|
||||
data, size = d.listData(value, check=True)
|
||||
d.putItemCount(size)
|
||||
|
||||
if d.qtVersion() >= 0x60000:
|
||||
d.qtVersionPing(value.typeid)
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
d.putPlotData(data, size, innerType)
|
||||
return
|
||||
|
||||
@@ -1145,9 +1145,9 @@ def qform__QImage():
|
||||
|
||||
|
||||
def qdump__QImage(d, value):
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
vtbl, painters, image_data = value.split('ppp')
|
||||
elif d.qtVersion() >= 0x050000:
|
||||
elif d.qtVersionAtLeast(0x050000):
|
||||
vtbl, painters, reserved, image_data = value.split('pppp')
|
||||
else:
|
||||
vtbl, painters, image_data = value.split('ppp')
|
||||
@@ -1161,12 +1161,12 @@ def qdump__QImage(d, value):
|
||||
|
||||
d.putExpandable()
|
||||
if d.isExpanded():
|
||||
if d.qtVersion() < 0x060000:
|
||||
(ref, width, height, depth, nbytes, pad, devicePixelRatio, colorTable,
|
||||
bits, iformat) = d.split('iiiii@dppi', image_data)
|
||||
else:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
(ref, width, height, depth, nbytes, pad, devicePixelRatio, _, _, _,
|
||||
bits, iformat) = d.split('iiiii@dppppi', image_data)
|
||||
else:
|
||||
(ref, width, height, depth, nbytes, pad, devicePixelRatio, colorTable,
|
||||
bits, iformat) = d.split('iiiii@dppi', image_data)
|
||||
with Children(d):
|
||||
d.putIntItem('width', width)
|
||||
d.putIntItem('height', height)
|
||||
@@ -1222,8 +1222,7 @@ def qdump__QLocale(d, value):
|
||||
# index = int(value['d']['d']['m_data']...)
|
||||
#d.check(index >= 0)
|
||||
#d.check(index <= qqLocalesCount)
|
||||
qtVersion = d.qtVersion()
|
||||
if qtVersion < 0x50000:
|
||||
if not d.qtVersionAtLeast(0x50000):
|
||||
d.putStringValue(d.call('const char *', value, 'name'))
|
||||
d.putPlainChildren(value)
|
||||
return
|
||||
@@ -1240,7 +1239,7 @@ def qdump__QLocale(d, value):
|
||||
|
||||
prefix = ns + 'QLocale::'
|
||||
try:
|
||||
if qtVersion >= 0x060700:
|
||||
if qtVersionAtLeast(0x060700):
|
||||
res = d.call('const char *', value, 'name', prefix + 'TagSeparator::Underscore')
|
||||
else:
|
||||
res = d.call('const char *', value, 'name')
|
||||
@@ -1347,9 +1346,9 @@ def qdump__QMap(d, value):
|
||||
|
||||
|
||||
def qdumpHelper_QMap(d, value, keyType, valueType):
|
||||
if d.qtVersion() >= 0x60000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
qdumpHelper_Qt6_QMap(d, value, keyType, valueType)
|
||||
elif d.qtVersion() >= 0x50000:
|
||||
elif d.qtVersionAtLeast(0x50000):
|
||||
qdumpHelper_Qt5_QMap(d, value, keyType, valueType)
|
||||
else:
|
||||
qdumpHelper_Qt4_QMap(d, value, keyType, valueType)
|
||||
@@ -1369,7 +1368,7 @@ def qdumpHelper_Qt6_QMultiMap(d, value, keyType, valueType):
|
||||
d.putBetterType('@QMultiMap<%s, %s>' % (keyType.name, valueType.name))
|
||||
|
||||
def qdump__QMultiMap(d, value):
|
||||
if d.qtVersion() >= 0x60000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
qdumpHelper_Qt6_QMultiMap(d, value, value.type[0], value.type[1])
|
||||
else:
|
||||
qdump__QMap(d, value)
|
||||
@@ -1449,9 +1448,9 @@ def qdump__QProcEnvKey(d, value):
|
||||
|
||||
|
||||
def qdump__QPixmap(d, value):
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
vtbl, painters, data = value.split('ppp')
|
||||
elif d.qtVersion() >= 0x050000:
|
||||
elif d.qtVersionAtLeast(0x050000):
|
||||
vtbl, painters, reserved, data = s = d.split('pppp', value)
|
||||
else:
|
||||
vtbl, painters, data = value.split('ppp')
|
||||
@@ -1518,15 +1517,15 @@ def qdump__QRegion(d, value):
|
||||
if d_ptr == 0:
|
||||
d.putSpecialValue('empty')
|
||||
else:
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
ref, _, rgn = d.split('i@p', d_ptr)
|
||||
numRects, innerArea, rects, extents, innerRect = \
|
||||
d.split('ii{@QList<@QRect>}{@QRect}{@QRect}', rgn)
|
||||
elif d.qtVersion() >= 0x050400: # Padding removed in ee324e4ed
|
||||
elif d.qtVersionAtLeast(0x050400): # Padding removed in ee324e4ed
|
||||
ref, _, rgn = d.split('i@p', d_ptr)
|
||||
numRects, innerArea, rects, extents, innerRect = \
|
||||
d.split('ii{@QVector<@QRect>}{@QRect}{@QRect}', rgn)
|
||||
elif d.qtVersion() >= 0x050000:
|
||||
elif d.qtVersionAtLeast(0x050000):
|
||||
ref, _, rgn = d.split('i@p', d_ptr)
|
||||
numRects, _, rects, extents, innerRect, innerArea = \
|
||||
d.split('i@{@QVector<@QRect>}{@QRect}{@QRect}i', rgn)
|
||||
@@ -1564,7 +1563,7 @@ def qdump__QScopedPointer(d, value):
|
||||
|
||||
|
||||
def qdump__QSet(d, value):
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
qdumpHelper_QSet6(d, value)
|
||||
else:
|
||||
qdumpHelper_QSet45(d, value)
|
||||
@@ -1637,7 +1636,7 @@ def qdumpHelper_QSet45(d, value):
|
||||
d.putItemCount(length)
|
||||
if d.isExpanded():
|
||||
keyType = value.type[0]
|
||||
isShort = d.qtVersion() < 0x050000 and keyType.name == 'int'
|
||||
isShort = not d.qtVersionAtLeast(0x050000) and keyType.name == 'int'
|
||||
with Children(d, length, childType=keyType):
|
||||
node = hashDataFirstNode()
|
||||
for i in d.childRange():
|
||||
@@ -1714,7 +1713,7 @@ def qform__QStack():
|
||||
|
||||
|
||||
def qdump__QStack(d, value):
|
||||
if d.qtVersion() >= 0x60000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
qdump__QList(d, value)
|
||||
else:
|
||||
qdump__QVector(d, value)
|
||||
@@ -1734,7 +1733,7 @@ def qdump__QPolygon(d, value):
|
||||
|
||||
def qdump__QGraphicsPolygonItem(d, value):
|
||||
(vtbl, dptr) = value.split('pp')
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
if d.ptrSize() == 8:
|
||||
offset = 424 # sizeof(QGraphicsPolygonItemPrivate), the base
|
||||
else:
|
||||
@@ -1764,6 +1763,7 @@ def qform__QString():
|
||||
|
||||
|
||||
def qdump__QString(d, value):
|
||||
d.qtVersionPing(value.typeid)
|
||||
d.putStringValue(value)
|
||||
data, length, _ = d.stringData(value)
|
||||
displayFormat = d.currentItemFormat()
|
||||
@@ -1924,7 +1924,7 @@ def qdump__QUrl(d, value):
|
||||
d.putValue('<invalid>')
|
||||
return
|
||||
|
||||
if d.qtVersion() < 0x050000:
|
||||
if not d.qtVersionAtLeast(0x050000):
|
||||
d.call('void', value, 'port') # Warm up internal cache.
|
||||
d.call('void', value, 'path')
|
||||
st = '{@QString}'
|
||||
@@ -2154,7 +2154,8 @@ qdumpHelper_QVariants_F = [
|
||||
|
||||
|
||||
def qdump__QVariant(d, value):
|
||||
if d.qtVersion() >= 0x060000:
|
||||
d.qtVersionPing(value.typeid, 2 * d.ptrSize())
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
qdumpHelper__QVariant6(d, value)
|
||||
else:
|
||||
qdumpHelper__QVariant45(d, value)
|
||||
@@ -2208,12 +2209,12 @@ def qdumpHelper__QVariant45(d, value):
|
||||
return None
|
||||
|
||||
# Extended Core type (Qt 5)
|
||||
if variantType >= 31 and variantType <= 38 and d.qtVersion() >= 0x050000:
|
||||
if variantType >= 31 and variantType <= 38 and d.qtVersionAtLeast(0x050000):
|
||||
qdumpHelper_QVariants_D[variantType - 31](d, value)
|
||||
return None
|
||||
|
||||
# Extended Core type (Qt 4)
|
||||
if variantType >= 128 and variantType <= 135 and d.qtVersion() < 0x050000:
|
||||
if variantType >= 128 and variantType <= 135 and not d.qtVersionAtLeast(0x050000):
|
||||
if variantType == 128:
|
||||
d.putBetterType('@QVariant (void *)')
|
||||
d.putValue('0x%x' % value.extractPointer())
|
||||
@@ -2234,7 +2235,7 @@ def qdumpHelper__QVariant45(d, value):
|
||||
innert = qdumpHelper_QVariants_B[variantType - 7]
|
||||
elif variantType <= 74:
|
||||
innert = qdumpHelper_QVariants_E[variantType - 64]
|
||||
elif d.qtVersion() < 0x050000:
|
||||
elif not d.qtVersionAtLeast(0x050000):
|
||||
innert = qdumpHelper_QVariants_F[variantType - 76]
|
||||
else:
|
||||
innert = qdumpHelper_QVariants_F[variantType - 75]
|
||||
@@ -2308,7 +2309,8 @@ def qform__QVector():
|
||||
|
||||
|
||||
def qdump__QVector(d, value):
|
||||
if d.qtVersion() >= 0x060000:
|
||||
d.qtVersionPing(value.typeid)
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
data, length = d.listData(value)
|
||||
d.putItemCount(length)
|
||||
d.putPlotData(data, length, value.type.target()[0])
|
||||
@@ -2330,7 +2332,7 @@ if False:
|
||||
|
||||
|
||||
def qdump__QVarLengthArray(d, value):
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
cap, length, data = value.split('QQp')
|
||||
else:
|
||||
cap, length, data = value.split('iip')
|
||||
@@ -2366,7 +2368,7 @@ def qdump_QWeakPointerHelper(d, value, isWeak, innerType=None):
|
||||
d.putValue('<invalid>')
|
||||
return
|
||||
|
||||
if d.qtVersion() >= 0x050000:
|
||||
if d.qtVersionAtLeast(0x050000):
|
||||
(weakref, strongref) = d.split('ii', d_ptr)
|
||||
else:
|
||||
(vptr, weakref, strongref) = d.split('pii', d_ptr)
|
||||
@@ -2872,7 +2874,7 @@ def qdump__QJSValue(d, value):
|
||||
if d.ptrSize() == 4:
|
||||
qdump_32__QJSValue(d, value)
|
||||
else:
|
||||
if d.qtVersion() >= 0x60000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
qdump_64__QJSValue_6(d, value)
|
||||
else:
|
||||
qdump_64__QJSValue_5(d, value)
|
||||
@@ -2906,7 +2908,7 @@ def qdump_64__QJSValue_6(d, value):
|
||||
if dd == 0:
|
||||
d.putValue('(undefined)')
|
||||
d.putType(value.type.name + ' (undefined)')
|
||||
if d.qtVersion() < 0x60500:
|
||||
if not d.qtVersionAtLeast(0x60500):
|
||||
typ = dd >> 47
|
||||
if typ == 5:
|
||||
d.putValue('(null)')
|
||||
@@ -3326,7 +3328,7 @@ def qdumpHelper_QJsonObject(d, data, obj):
|
||||
def qdump__QJsonValue(d, value):
|
||||
(data, dd, t) = value.split('QpI')
|
||||
|
||||
if d.qtVersion() >= 0x050f00:
|
||||
if d.qtVersionAtLeast(0x050f00):
|
||||
value = d.createProxyValue((data, dd, t, False), 'QCborValue_proxy')
|
||||
d.putItem(value)
|
||||
return
|
||||
@@ -3361,13 +3363,13 @@ def qdump__QJsonValue(d, value):
|
||||
|
||||
|
||||
def qdump__QJsonArray(d, value):
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
dptr = d.extractPointer(value)
|
||||
if not dptr:
|
||||
d.putItemCount(0)
|
||||
else:
|
||||
qdumpHelper_QCbor_array(d, dptr, False)
|
||||
elif d.qtVersion() >= 0x050f00:
|
||||
elif d.qtVersionAtLeast(0x050f00):
|
||||
_, container_ptr = value.split('pp')
|
||||
qdumpHelper_QCbor_array(d, container_ptr, False)
|
||||
else:
|
||||
@@ -3375,13 +3377,13 @@ def qdump__QJsonArray(d, value):
|
||||
|
||||
|
||||
def qdump__QJsonObject(d, value):
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
dptr = d.extractPointer(value)
|
||||
if not dptr:
|
||||
d.putItemCount(0)
|
||||
else:
|
||||
qdumpHelper_QCbor_map(d, dptr, False)
|
||||
elif d.qtVersion() >= 0x050f00:
|
||||
elif d.qtVersionAtLeast(0x050f00):
|
||||
_, container_ptr = value.split('pp')
|
||||
qdumpHelper_QCbor_map(d, container_ptr, False)
|
||||
else:
|
||||
@@ -3456,15 +3458,15 @@ def qdump__qfloat16(d, value):
|
||||
def qdumpHelper_QCbor_string(d, container_ptr, element_index, is_bytes):
|
||||
# d.split('i@{@QByteArray::size_type}pp', container_ptr) doesn't work with CDB,
|
||||
# so be explicit:
|
||||
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8)
|
||||
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersion() >= 0x060000 else d.ptrSize())
|
||||
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else 8)
|
||||
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else d.ptrSize())
|
||||
elements_data_ptr, elements_size = d.vectorData(elements_pos)
|
||||
element_at_n_addr = elements_data_ptr + element_index * 16 # sizeof(QtCbor::Element) == 16
|
||||
element_value, _, element_flags = d.split('qII', element_at_n_addr)
|
||||
enc = 'latin1' if is_bytes or (element_flags & 8) else 'utf16'
|
||||
bytedata, _, _ = d.qArrayData(data_pos)
|
||||
bytedata += element_value
|
||||
if d.qtVersion() >= 0x060000:
|
||||
if d.qtVersionAtLeast(0x060000):
|
||||
bytedata_len = d.extractInt64(bytedata)
|
||||
bytedata_data = bytedata + 8
|
||||
else:
|
||||
@@ -3493,8 +3495,8 @@ def qdumpHelper_QCbor_array(d, container_ptr, is_cbor):
|
||||
return
|
||||
# d.split('i@{@QByteArray::size_type}pp', container_ptr) doesn't work with CDB,
|
||||
# so be explicit:
|
||||
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8)
|
||||
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersion() >= 0x060000 else d.ptrSize())
|
||||
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else 8)
|
||||
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else d.ptrSize())
|
||||
elements_data_ptr, elements_size = d.vectorData(elements_pos)
|
||||
d.putItemCount(elements_size)
|
||||
if d.isExpanded():
|
||||
@@ -3515,8 +3517,8 @@ def qdumpHelper_QCbor_map(d, container_ptr, is_cbor):
|
||||
return
|
||||
# d.split('i@{@QByteArray::size_type}pp', container_ptr) doesn't work with CDB,
|
||||
# so be explicit:
|
||||
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8)
|
||||
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersion() >= 0x060000 else d.ptrSize())
|
||||
data_pos = container_ptr + (2 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else 8)
|
||||
elements_pos = data_pos + (3 * d.ptrSize() if d.qtVersionAtLeast(0x060000) else d.ptrSize())
|
||||
elements_data_ptr, elements_size = d.vectorData(elements_pos)
|
||||
elements_size = int(elements_size / 2)
|
||||
d.putItemCount(elements_size)
|
||||
|
@@ -844,11 +844,9 @@ Utils::expected_str<void> PluginSpecPrivate::readMetaData(const QJsonObject &dat
|
||||
value = metaData.value(QLatin1String(PLUGIN_DISABLED_BY_DEFAULT));
|
||||
if (!value.isUndefined() && !value.isBool())
|
||||
return reportError(msgValueIsNotABool(PLUGIN_DISABLED_BY_DEFAULT));
|
||||
enabledByDefault = !value.toBool(false);
|
||||
enabledByDefault = !value.toBool(experimental || deprecated);
|
||||
qCDebug(pluginLog) << "enabledByDefault =" << enabledByDefault;
|
||||
|
||||
if (experimental || deprecated)
|
||||
enabledByDefault = false;
|
||||
enabledBySettings = enabledByDefault;
|
||||
|
||||
value = metaData.value(QLatin1String(PLUGIN_SOFTLOADABLE));
|
||||
|
@@ -261,6 +261,12 @@ DocumentHighlightsResult::DocumentHighlightsResult(const QJsonValue &value)
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
MarkedString fromJsonValue<MarkedString>(const QJsonValue &value)
|
||||
{
|
||||
return MarkedString(value);
|
||||
}
|
||||
|
||||
MarkedString::MarkedString(const QJsonValue &value)
|
||||
{
|
||||
if (value.isObject())
|
||||
|
@@ -52,6 +52,9 @@ public:
|
||||
operator QJsonValue() const;
|
||||
};
|
||||
|
||||
template<>
|
||||
LANGUAGESERVERPROTOCOL_EXPORT MarkedString fromJsonValue<MarkedString>(const QJsonValue &value);
|
||||
|
||||
class LANGUAGESERVERPROTOCOL_EXPORT HoverContent
|
||||
: public std::variant<MarkedString, QList<MarkedString>, MarkupContent>
|
||||
{
|
||||
|
@@ -68,7 +68,7 @@ public:
|
||||
if (value.isArray()) {
|
||||
QList<T> values;
|
||||
values.reserve(value.toArray().count());
|
||||
for (auto arrayValue : value.toArray())
|
||||
for (const auto &arrayValue : value.toArray())
|
||||
values << fromJsonValue<T>(arrayValue);
|
||||
*this = values;
|
||||
} else {
|
||||
|
@@ -24,7 +24,7 @@ void Barrier::start()
|
||||
{
|
||||
QT_ASSERT(!isRunning(), return);
|
||||
m_current = 0;
|
||||
m_result = {};
|
||||
m_result.reset();
|
||||
}
|
||||
|
||||
void Barrier::advance()
|
||||
|
@@ -1450,6 +1450,11 @@ ExecutableItem ExecutableItem::withTimeout(milliseconds timeout,
|
||||
|
||||
static QString currentTime() { return QTime::currentTime().toString(Qt::ISODateWithMs); }
|
||||
|
||||
static QString logHeader(const QString &logName)
|
||||
{
|
||||
return QString::fromLatin1("TASK TREE LOG [%1] \"%2\"").arg(currentTime(), logName);
|
||||
};
|
||||
|
||||
/*!
|
||||
Attaches a custom debug printout to a copy of \c this ExecutableItem,
|
||||
issued on task startup and after the task is finished, and returns the coupled item.
|
||||
@@ -1463,9 +1468,6 @@ static QString currentTime() { return QTime::currentTime().toString(Qt::ISODateW
|
||||
*/
|
||||
ExecutableItem ExecutableItem::withLog(const QString &logName) const
|
||||
{
|
||||
const auto header = [logName] {
|
||||
return QString::fromLatin1("TASK TREE LOG [%1] \"%2\"").arg(currentTime(), logName);
|
||||
};
|
||||
struct LogStorage
|
||||
{
|
||||
time_point<system_clock, nanoseconds> start;
|
||||
@@ -1474,21 +1476,22 @@ ExecutableItem ExecutableItem::withLog(const QString &logName) const
|
||||
const Storage<LogStorage> storage;
|
||||
return Group {
|
||||
storage,
|
||||
onGroupSetup([storage, header] {
|
||||
onGroupSetup([storage, logName] {
|
||||
storage->start = system_clock::now();
|
||||
storage->asyncCount = activeTaskTree()->asyncCount();
|
||||
qDebug().noquote() << header() << "started.";
|
||||
qDebug().noquote().nospace() << logHeader(logName) << " started.";
|
||||
}),
|
||||
*this,
|
||||
onGroupDone([storage, header](DoneWith result) {
|
||||
onGroupDone([storage, logName](DoneWith result) {
|
||||
const auto elapsed = duration_cast<milliseconds>(system_clock::now() - storage->start);
|
||||
const int asyncCountDiff = activeTaskTree()->asyncCount() - storage->asyncCount;
|
||||
QT_CHECK(asyncCountDiff >= 0);
|
||||
const QMetaEnum doneWithEnum = QMetaEnum::fromType<DoneWith>();
|
||||
const QString syncType = asyncCountDiff ? QString::fromLatin1("asynchronously")
|
||||
: QString::fromLatin1("synchronously");
|
||||
qDebug().noquote().nospace() << header() << " finished " << syncType << " with "
|
||||
<< doneWithEnum.valueToKey(int(result)) << " within " << elapsed.count() << "ms.";
|
||||
qDebug().noquote().nospace() << logHeader(logName) << " finished " << syncType
|
||||
<< " with " << doneWithEnum.valueToKey(int(result))
|
||||
<< " within " << elapsed.count() << "ms.";
|
||||
})
|
||||
};
|
||||
}
|
||||
@@ -3383,7 +3386,7 @@ TimeoutTaskAdapter::~TimeoutTaskAdapter()
|
||||
void TimeoutTaskAdapter::start()
|
||||
{
|
||||
m_timerId = scheduleTimeout(*task(), this, [this] {
|
||||
m_timerId = {};
|
||||
m_timerId.reset();
|
||||
emit done(DoneResult::Success);
|
||||
});
|
||||
}
|
||||
|
@@ -29,23 +29,6 @@ QTCREATOR_UTILS_EXPORT QString fileNameToCppIdentifier(const QString &s)
|
||||
return rc;
|
||||
}
|
||||
|
||||
QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file)
|
||||
{
|
||||
return headerGuard(file, QStringList());
|
||||
}
|
||||
|
||||
QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file, const QStringList &namespaceList)
|
||||
{
|
||||
const QChar underscore = QLatin1Char('_');
|
||||
QString rc;
|
||||
for (int i = 0; i < namespaceList.count(); i++)
|
||||
rc += namespaceList.at(i).toUpper() + underscore;
|
||||
|
||||
const QFileInfo fi(file);
|
||||
rc += fileNameToCppIdentifier(fi.fileName()).toUpper();
|
||||
return rc;
|
||||
}
|
||||
|
||||
QTCREATOR_UTILS_EXPORT
|
||||
void writeIncludeFileDirective(const QString &file, bool globalInclude,
|
||||
QTextStream &str)
|
||||
|
@@ -17,9 +17,6 @@ namespace Utils {
|
||||
// or replacing them by an underscore).
|
||||
QTCREATOR_UTILS_EXPORT QString fileNameToCppIdentifier(const QString &s);
|
||||
|
||||
QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file);
|
||||
QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file, const QStringList &namespaceList);
|
||||
|
||||
QTCREATOR_UTILS_EXPORT
|
||||
void writeIncludeFileDirective(const QString &file,
|
||||
bool globalInclude,
|
||||
|
@@ -3,6 +3,7 @@
|
||||
"Version" : "${IDE_VERSION}",
|
||||
"CompatVersion" : "${IDE_VERSION_COMPAT}",
|
||||
"Experimental" : true,
|
||||
"DisabledByDefault" : ${APPSTATISTICSMONITOR_DISABLEDBYDEFAULT},
|
||||
"Vendor" : "The Qt Company Ltd",
|
||||
"Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd",
|
||||
"License" : [ "Commercial Usage",
|
||||
|
@@ -13,6 +13,8 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
find_package(Qt6 COMPONENTS Charts QUIET)
|
||||
|
||||
set(APPSTATISTICSMONITOR_DISABLEDBYDEFAULT "true")
|
||||
|
||||
if (NOT QT_CREATOR_API_DEFINED)
|
||||
# standalone build
|
||||
set(DESTINATION DESTINATION .)
|
||||
@@ -21,6 +23,8 @@ if (NOT QT_CREATOR_API_DEFINED)
|
||||
qtc_handle_compiler_cache_support()
|
||||
|
||||
find_package(QtCreator COMPONENTS Core ProjectExplorer Utils REQUIRED)
|
||||
|
||||
set(APPSTATISTICSMONITOR_DISABLEDBYDEFAULT "false")
|
||||
endif()
|
||||
|
||||
|
||||
|
@@ -51,6 +51,8 @@ using namespace Utils;
|
||||
|
||||
namespace Axivion::Internal {
|
||||
|
||||
void showIssuesFromDashboard(const QString &kind); // impl at bottom
|
||||
|
||||
class DashboardWidget : public QScrollArea
|
||||
{
|
||||
public:
|
||||
@@ -147,14 +149,24 @@ void DashboardWidget::updateUi()
|
||||
}
|
||||
return prefix;
|
||||
};
|
||||
auto addValuesWidgets = [this, &toolTip](const QString &issueKind, qint64 total, qint64 added, qint64 removed, int row) {
|
||||
auto linked = [](const QString &text, const QString &href, bool link) {
|
||||
return link ? QString("<a href='%1'>%2</a>").arg(href).arg(text)
|
||||
: text;
|
||||
};
|
||||
auto addValuesWidgets = [this, &toolTip, &linked](const QString &issueKind, qint64 total,
|
||||
qint64 added, qint64 removed, int row, bool link) {
|
||||
const QString currentToolTip = toolTip(issueKind);
|
||||
QLabel *label = new QLabel(issueKind, this);
|
||||
label->setToolTip(currentToolTip);
|
||||
m_gridLayout->addWidget(label, row, 0);
|
||||
label = new QLabel(QString::number(total), this);
|
||||
label = new QLabel(linked(QString::number(total), issueKind, link), this);
|
||||
label->setToolTip(currentToolTip);
|
||||
label->setAlignment(Qt::AlignRight);
|
||||
if (link) {
|
||||
connect(label, &QLabel::linkActivated, this, [](const QString &issueKind) {
|
||||
showIssuesFromDashboard(issueKind);
|
||||
});
|
||||
}
|
||||
m_gridLayout->addWidget(label, row, 1);
|
||||
label = new QLabel(this);
|
||||
label->setPixmap(trendIcon(added, removed));
|
||||
@@ -190,12 +202,12 @@ void DashboardWidget::updateUi()
|
||||
allAdded += added;
|
||||
qint64 removed = extract_value(counts, QStringLiteral("Removed"));
|
||||
allRemoved += removed;
|
||||
addValuesWidgets(issueCount.first, total, added, removed, row);
|
||||
addValuesWidgets(issueCount.first, total, added, removed, row, true);
|
||||
++row;
|
||||
}
|
||||
}
|
||||
}
|
||||
addValuesWidgets(Tr::tr("Total:"), allTotal, allAdded, allRemoved, row);
|
||||
addValuesWidgets(Tr::tr("Total:"), allTotal, allAdded, allRemoved, row, false);
|
||||
}
|
||||
|
||||
struct LinkWithColumns
|
||||
@@ -263,7 +275,7 @@ class IssuesWidget : public QScrollArea
|
||||
{
|
||||
public:
|
||||
explicit IssuesWidget(QWidget *parent = nullptr);
|
||||
void updateUi();
|
||||
void updateUi(const QString &kind);
|
||||
|
||||
const std::optional<Dto::TableInfoDto> currentTableInfo() const { return m_currentTableInfo; }
|
||||
IssueListSearch searchFromUi() const;
|
||||
@@ -378,7 +390,7 @@ IssuesWidget::IssuesWidget(QWidget *parent)
|
||||
setWidgetResizable(true);
|
||||
}
|
||||
|
||||
void IssuesWidget::updateUi()
|
||||
void IssuesWidget::updateUi(const QString &kind)
|
||||
{
|
||||
setFiltersEnabled(false);
|
||||
const std::optional<Dto::ProjectInfoDto> projectInfo = Internal::projectInfo();
|
||||
@@ -392,11 +404,30 @@ void IssuesWidget::updateUi()
|
||||
|
||||
setFiltersEnabled(true);
|
||||
// avoid refetching existing data
|
||||
if (!m_currentPrefix.isEmpty() || m_issuesModel->rowCount())
|
||||
if (kind.isEmpty() && (!m_currentPrefix.isEmpty() || m_issuesModel->rowCount()))
|
||||
return;
|
||||
|
||||
if (info.issueKinds.size())
|
||||
m_currentPrefix = info.issueKinds.front().prefix;
|
||||
if (!kind.isEmpty()) {
|
||||
const int index
|
||||
= Utils::indexOf( info.issueKinds, [kind](const Dto::IssueKindInfoDto &dto) {
|
||||
return dto.prefix == kind; });
|
||||
if (index != -1) {
|
||||
m_currentPrefix = kind;
|
||||
auto kindButton = m_typesButtonGroup->button(index + 1);
|
||||
if (QTC_GUARD(kindButton))
|
||||
kindButton->setChecked(true);
|
||||
// reset filters - if kind is not empty we get triggered from dashboard overview
|
||||
if (!m_userNames.isEmpty())
|
||||
m_ownerFilter->setCurrentIndex(0);
|
||||
m_pathGlobFilter->clear();
|
||||
if (m_versionDates.size() > 1) {
|
||||
m_versionStart->setCurrentIndex(m_versionDates.count() - 1);
|
||||
m_versionEnd->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_currentPrefix.isEmpty())
|
||||
m_currentPrefix = info.issueKinds.size() ? info.issueKinds.front().prefix : QString{};
|
||||
fetchTable();
|
||||
}
|
||||
|
||||
@@ -767,12 +798,7 @@ public:
|
||||
m_showIssues->setIcon(Icons::ZOOM_TOOLBAR.icon());
|
||||
m_showIssues->setToolTip(Tr::tr("Search for issues"));
|
||||
m_showIssues->setCheckable(true);
|
||||
connect(m_showIssues, &QToolButton::clicked, this, [this] {
|
||||
QTC_ASSERT(m_outputWidget, return);
|
||||
m_outputWidget->setCurrentIndex(1);
|
||||
if (auto issues = static_cast<IssuesWidget *>(m_outputWidget->widget(1)))
|
||||
issues->updateUi();
|
||||
});
|
||||
connect(m_showIssues, &QToolButton::clicked, this, [this] { handleShowIssues({}); });
|
||||
auto *butonGroup = new QButtonGroup(this);
|
||||
butonGroup->addButton(m_showDashboard);
|
||||
butonGroup->addButton(m_showIssues);
|
||||
@@ -814,6 +840,14 @@ public:
|
||||
void goToNext() final {}
|
||||
void goToPrev() final {}
|
||||
|
||||
void handleShowIssues(const QString &kind)
|
||||
{
|
||||
QTC_ASSERT(m_outputWidget, return);
|
||||
m_outputWidget->setCurrentIndex(1);
|
||||
if (auto issues = static_cast<IssuesWidget *>(m_outputWidget->widget(1)))
|
||||
issues->updateUi(kind);
|
||||
}
|
||||
|
||||
void updateDashboard()
|
||||
{
|
||||
if (auto dashboard = static_cast<DashboardWidget *>(m_outputWidget->widget(0))) {
|
||||
@@ -897,4 +931,10 @@ static bool issueListContextMenuEvent(const ItemViewEvent &ev)
|
||||
return theAxivionOutputPane->handleContextMenu(issue, ev);
|
||||
}
|
||||
|
||||
void showIssuesFromDashboard(const QString &kind)
|
||||
{
|
||||
QTC_ASSERT(theAxivionOutputPane, return);
|
||||
theAxivionOutputPane->handleShowIssues(kind);
|
||||
}
|
||||
|
||||
} // Axivion::Internal
|
||||
|
@@ -474,11 +474,10 @@ ClangTool::ClangTool(const QString &name, Id id, ClangToolType type)
|
||||
|
||||
// Expand/Collapse
|
||||
action = new QAction(this);
|
||||
action->setDisabled(true);
|
||||
action->setCheckable(true);
|
||||
action->setIcon(Utils::Icons::EXPAND_ALL_TOOLBAR.icon());
|
||||
action->setToolTip(Tr::tr("Expand All"));
|
||||
connect(action, &QAction::toggled, this, [this](bool checked){
|
||||
m_expandCollapse = action;
|
||||
const auto handleCollapseExpandToggled = [this](bool checked){
|
||||
if (checked) {
|
||||
m_expandCollapse->setToolTip(Tr::tr("Collapse All"));
|
||||
m_diagnosticView->expandAll();
|
||||
@@ -486,8 +485,9 @@ ClangTool::ClangTool(const QString &name, Id id, ClangToolType type)
|
||||
m_expandCollapse->setToolTip(Tr::tr("Expand All"));
|
||||
m_diagnosticView->collapseAll();
|
||||
}
|
||||
});
|
||||
m_expandCollapse = action;
|
||||
};
|
||||
connect(action, &QAction::toggled, this, handleCollapseExpandToggled);
|
||||
handleCollapseExpandToggled(action->isChecked());
|
||||
|
||||
// Filter button
|
||||
action = m_showFilter = new QAction(this);
|
||||
@@ -1242,8 +1242,32 @@ QSet<Diagnostic> ClangTool::diagnostics() const
|
||||
|
||||
void ClangTool::onNewDiagnosticsAvailable(const Diagnostics &diagnostics, bool generateMarks)
|
||||
{
|
||||
QTC_ASSERT(m_diagnosticModel, return);
|
||||
const int oldLevel1RowCount = m_diagnosticModel->rowCount();
|
||||
const auto getOldLastLevel1Index = [&] {
|
||||
return m_diagnosticModel->index(oldLevel1RowCount - 1, 0);
|
||||
};
|
||||
const auto getLevel2RowCountForOldLastLevel1Index = [&] {
|
||||
return oldLevel1RowCount == 0 ? -1 : m_diagnosticModel->rowCount(getOldLastLevel1Index());
|
||||
};
|
||||
const int oldLevel2RowCount = getLevel2RowCountForOldLastLevel1Index();
|
||||
m_diagnosticModel->addDiagnostics(diagnostics, generateMarks);
|
||||
if (!m_expandCollapse->isChecked())
|
||||
return;
|
||||
|
||||
// Now expand newly added items, both in existing file nodes and in newly added ones.
|
||||
// We assume diagnostics arrive "in order", i.e. things are only ever added at the end
|
||||
// (in the source model).
|
||||
const int newLevel2RowCount = getLevel2RowCountForOldLastLevel1Index();
|
||||
for (int i = oldLevel2RowCount; i < newLevel2RowCount; ++i) {
|
||||
m_diagnosticView->expand(m_diagnosticFilterModel->mapFromSource(
|
||||
m_diagnosticModel
|
||||
->index(i, 0, m_diagnosticFilterModel->mapFromSource(getOldLastLevel1Index()))));
|
||||
}
|
||||
const int newLevel1RowCount = m_diagnosticFilterModel->rowCount();
|
||||
for (int i = oldLevel1RowCount; i < newLevel1RowCount; ++i) {
|
||||
m_diagnosticView->expandRecursively(
|
||||
m_diagnosticFilterModel->mapFromSource(m_diagnosticModel->index(i, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
void ClangTool::updateForCurrentState()
|
||||
@@ -1273,7 +1297,6 @@ void ClangTool::updateForCurrentState()
|
||||
m_goBack->setEnabled(issuesVisible > 0);
|
||||
m_goNext->setEnabled(issuesVisible > 0);
|
||||
m_clear->setEnabled(!isRunning);
|
||||
m_expandCollapse->setEnabled(issuesVisible);
|
||||
m_loadExported->setEnabled(!isRunning);
|
||||
m_showFilter->setEnabled(issuesFound > 1);
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <cppeditor/clangdiagnosticconfigsmodel.h>
|
||||
#include <cppeditor/compileroptionsbuilder.h>
|
||||
#include <cppeditor/cppcodemodelsettings.h>
|
||||
#include <cppeditor/cppprojectfile.h>
|
||||
#include <cppeditor/cpptoolsreuse.h>
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#include <projectexplorer/devicesupport/idevice.h>
|
||||
#include <projectexplorer/environmentaspectwidget.h>
|
||||
#include <projectexplorer/environmentwidget.h>
|
||||
#include <projectexplorer/gcctoolchain.h>
|
||||
#include <projectexplorer/kitaspects.h>
|
||||
#include <projectexplorer/namedwidget.h>
|
||||
#include <projectexplorer/processparameters.h>
|
||||
@@ -1184,30 +1183,6 @@ static CommandLine defaultInitialCMakeCommand(
|
||||
}
|
||||
}
|
||||
|
||||
// GCC compiler and linker specific flags
|
||||
for (Toolchain *tc : ToolchainKitAspect::toolChains(k)) {
|
||||
if (auto *gccTc = tc->asGccToolchain()) {
|
||||
const QStringList compilerFlags = gccTc->platformCodeGenFlags();
|
||||
|
||||
QLatin1String languageFlagsInit;
|
||||
if (gccTc->language() == ProjectExplorer::Constants::C_LANGUAGE_ID)
|
||||
languageFlagsInit = QLatin1String(CMAKE_C_FLAGS_INIT);
|
||||
else if (gccTc->language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
|
||||
languageFlagsInit = QLatin1String(CMAKE_CXX_FLAGS_INIT);
|
||||
|
||||
if (!languageFlagsInit.isEmpty() && !compilerFlags.isEmpty())
|
||||
cmd.addArg("-D" + languageFlagsInit + ":STRING=" + compilerFlags.join(" "));
|
||||
|
||||
const QStringList linkerFlags = gccTc->platformLinkerFlags();
|
||||
if (!linkerFlags.isEmpty()) {
|
||||
const QString joinedLinkerFlags = linkerFlags.join(" ");
|
||||
cmd.addArg("-DCMAKE_EXE_LINKER_FLAGS_INIT:STRING=" + joinedLinkerFlags);
|
||||
cmd.addArg("-DCMAKE_MODULE_LINKER_FLAGS_INIT:STRING=" + joinedLinkerFlags);
|
||||
cmd.addArg("-DCMAKE_SHARED_LINKER_FLAGS_INIT:STRING=" + joinedLinkerFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmd.addArgs(CMakeConfigurationKitAspect::toArgumentsList(k));
|
||||
cmd.addArgs(CMakeConfigurationKitAspect::additionalConfiguration(k), CommandLine::Raw);
|
||||
|
||||
@@ -1356,7 +1331,7 @@ static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArgume
|
||||
|
||||
if (argFilePath != presetFilePath)
|
||||
arg = presetItem.toArgument();
|
||||
} else if (argItem.key == CMAKE_CXX_FLAGS_INIT) {
|
||||
} else if (argItem.key == CMAKE_C_FLAGS_INIT || argItem.key == CMAKE_CXX_FLAGS_INIT) {
|
||||
// Append the preset value with at the initial parameters value (e.g. QML Debugging)
|
||||
if (argItem.expandedValue(k) != QString::fromUtf8(presetItem.value)) {
|
||||
argItem.value.append(" ");
|
||||
|
@@ -227,7 +227,7 @@ void CppEditorPlugin::initialize()
|
||||
void CppEditorPlugin::extensionsInitialized()
|
||||
{
|
||||
setupCppQuickFixProjectPanel();
|
||||
setupCppFileSettings();
|
||||
setupCppFileSettings(*this);
|
||||
setupCppCodeModelProjectSettingsPanel();
|
||||
|
||||
if (CppModelManager::isClangCodeModelActive()) {
|
||||
|
@@ -6,15 +6,19 @@
|
||||
#include "cppeditortr.h"
|
||||
#include "cppheadersource.h"
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectpanelfactory.h>
|
||||
|
||||
#include <utils/aspects.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/layoutbuilder.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/mimeconstants.h>
|
||||
#include <utils/mimeutils.h>
|
||||
#include <utils/pathchooser.h>
|
||||
@@ -29,10 +33,30 @@
|
||||
#include <QTextStream>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
#include <QtTest>
|
||||
#endif
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace CppEditor::Internal {
|
||||
namespace {
|
||||
class HeaderGuardExpander : public MacroExpander
|
||||
{
|
||||
public:
|
||||
HeaderGuardExpander(const FilePath &filePath) : m_filePath(filePath)
|
||||
{
|
||||
setDisplayName(Tr::tr("Header file variables"));
|
||||
registerFileVariables("Header", Tr::tr("Header file"), [this] {
|
||||
return m_filePath;
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
const FilePath m_filePath;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
const char projectSettingsKeyC[] = "CppEditorFileNames";
|
||||
const char useGlobalKeyC[] = "UseGlobal";
|
||||
@@ -44,6 +68,7 @@ const char headerSearchPathsKeyC[] = "HeaderSearchPaths";
|
||||
const char sourceSearchPathsKeyC[] = "SourceSearchPaths";
|
||||
const char headerPragmaOnceC[] = "HeaderPragmaOnce";
|
||||
const char licenseTemplatePathKeyC[] = "LicenseTemplate";
|
||||
const char headerGuardTemplateKeyC[] = "HeaderGuardTemplate";
|
||||
|
||||
const char *licenseTemplateTemplate = QT_TRANSLATE_NOOP("QtC::CppEditor",
|
||||
"/**************************************************************************\n"
|
||||
@@ -67,6 +92,7 @@ void CppFileSettings::toSettings(QtcSettings *s) const
|
||||
s->setValueWithDefault(headerPragmaOnceC, headerPragmaOnce, def.headerPragmaOnce);
|
||||
s->setValueWithDefault(licenseTemplatePathKeyC, licenseTemplatePath.toSettings(),
|
||||
def.licenseTemplatePath.toSettings());
|
||||
s->setValueWithDefault(headerGuardTemplateKeyC, headerGuardTemplate, def.headerGuardTemplate);
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
@@ -84,6 +110,7 @@ void CppFileSettings::fromSettings(QtcSettings *s)
|
||||
headerPragmaOnce = s->value(headerPragmaOnceC, def.headerPragmaOnce).toBool();
|
||||
licenseTemplatePath = FilePath::fromSettings(s->value(licenseTemplatePathKeyC,
|
||||
def.licenseTemplatePath.toSettings()));
|
||||
headerGuardTemplate = s->value(headerGuardTemplateKeyC, def.headerGuardTemplate).toString();
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
@@ -124,6 +151,7 @@ bool CppFileSettings::equals(const CppFileSettings &rhs) const
|
||||
&& sourceSuffix == rhs.sourceSuffix
|
||||
&& headerSearchPaths == rhs.headerSearchPaths
|
||||
&& sourceSearchPaths == rhs.sourceSearchPaths
|
||||
&& headerGuardTemplate == rhs.headerGuardTemplate
|
||||
&& licenseTemplatePath == rhs.licenseTemplatePath;
|
||||
}
|
||||
|
||||
@@ -237,6 +265,11 @@ QString CppFileSettings::licenseTemplate() const
|
||||
return license;
|
||||
}
|
||||
|
||||
QString CppFileSettings::headerGuard(const Utils::FilePath &headerFilePath) const
|
||||
{
|
||||
return HeaderGuardExpander(headerFilePath).expand(headerGuardTemplate);
|
||||
}
|
||||
|
||||
// ------------------ CppFileSettingsWidget
|
||||
|
||||
class CppFileSettingsWidget final : public Core::IOptionsPageWidget
|
||||
@@ -269,6 +302,8 @@ private:
|
||||
QLineEdit *m_sourcePrefixesEdit = nullptr;
|
||||
QCheckBox *m_lowerCaseFileNamesCheckBox = nullptr;
|
||||
PathChooser *m_licenseTemplatePathChooser = nullptr;
|
||||
StringAspect m_headerGuardAspect;
|
||||
HeaderGuardExpander m_headerGuardExpander{{}};
|
||||
};
|
||||
|
||||
CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
@@ -276,7 +311,7 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
, m_headerSuffixComboBox(new QComboBox)
|
||||
, m_headerSearchPathsEdit(new QLineEdit)
|
||||
, m_headerPrefixesEdit(new QLineEdit)
|
||||
, m_headerPragmaOnceCheckBox(new QCheckBox(Tr::tr("Use \"#pragma once\" instead of \"#ifndef\" guards")))
|
||||
, m_headerPragmaOnceCheckBox(new QCheckBox(Tr::tr("Use \"#pragma once\" instead")))
|
||||
, m_sourceSuffixComboBox(new QComboBox)
|
||||
, m_sourceSearchPathsEdit(new QLineEdit)
|
||||
, m_sourcePrefixesEdit(new QLineEdit)
|
||||
@@ -301,6 +336,8 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
m_sourcePrefixesEdit->setToolTip(Tr::tr("Comma-separated list of source prefixes.\n"
|
||||
"\n"
|
||||
"These prefixes are used in addition to current file name on Switch Header/Source."));
|
||||
m_headerGuardAspect.setDisplayStyle(Utils::StringAspect::LineEditDisplay);
|
||||
m_headerGuardAspect.setMacroExpander(&m_headerGuardExpander);
|
||||
|
||||
using namespace Layouting;
|
||||
|
||||
@@ -311,8 +348,8 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
Tr::tr("&Suffix:"), m_headerSuffixComboBox, st, br,
|
||||
Tr::tr("S&earch paths:"), m_headerSearchPathsEdit, br,
|
||||
Tr::tr("&Prefixes:"), m_headerPrefixesEdit, br,
|
||||
Tr::tr("Include guards"), m_headerPragmaOnceCheckBox
|
||||
}
|
||||
Tr::tr("Include guard template:"), m_headerPragmaOnceCheckBox, m_headerGuardAspect
|
||||
},
|
||||
},
|
||||
Group {
|
||||
title(Tr::tr("Sources")),
|
||||
@@ -361,12 +398,21 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
connect(m_sourcePrefixesEdit, &QLineEdit::textEdited,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
connect(m_headerPragmaOnceCheckBox, &QCheckBox::stateChanged,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
connect(m_lowerCaseFileNamesCheckBox, &QCheckBox::stateChanged,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
connect(m_licenseTemplatePathChooser, &PathChooser::textChanged,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
const auto updateHeaderGuardAspectState = [this] {
|
||||
m_headerGuardAspect.setEnabled(!m_headerPragmaOnceCheckBox->isChecked());
|
||||
};
|
||||
connect(m_headerPragmaOnceCheckBox, &QCheckBox::stateChanged,
|
||||
this, [this, updateHeaderGuardAspectState] {
|
||||
updateHeaderGuardAspectState();
|
||||
emit userChange();
|
||||
});
|
||||
connect(&m_headerGuardAspect, &StringAspect::changed,
|
||||
this, &CppFileSettingsWidget::userChange);
|
||||
updateHeaderGuardAspectState();
|
||||
}
|
||||
|
||||
FilePath CppFileSettingsWidget::licenseTemplatePath() const
|
||||
@@ -417,6 +463,7 @@ void CppFileSettingsWidget::setSettings(const CppFileSettings &s)
|
||||
m_headerSearchPathsEdit->setText(s.headerSearchPaths.join(comma));
|
||||
m_sourceSearchPathsEdit->setText(s.sourceSearchPaths.join(comma));
|
||||
setLicenseTemplatePath(s.licenseTemplatePath);
|
||||
m_headerGuardAspect.setValue(s.headerGuardTemplate);
|
||||
}
|
||||
|
||||
CppFileSettings CppFileSettingsWidget::currentSettings() const
|
||||
@@ -431,6 +478,7 @@ CppFileSettings CppFileSettingsWidget::currentSettings() const
|
||||
rc.headerSearchPaths = trimmedPaths(m_headerSearchPathsEdit->text());
|
||||
rc.sourceSearchPaths = trimmedPaths(m_sourceSearchPathsEdit->text());
|
||||
rc.licenseTemplatePath = licenseTemplatePath();
|
||||
rc.headerGuardTemplate = m_headerGuardAspect.value();
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -536,6 +584,8 @@ void CppFileSettingsForProject::loadSettings()
|
||||
m_customSettings.lowerCaseFiles).toBool();
|
||||
m_customSettings.headerPragmaOnce = data.value(headerPragmaOnceC,
|
||||
m_customSettings.headerPragmaOnce).toBool();
|
||||
m_customSettings.headerGuardTemplate
|
||||
= data.value(headerGuardTemplateKeyC, m_customSettings.headerGuardTemplate).toString();
|
||||
m_customSettings.licenseTemplatePath
|
||||
= FilePath::fromSettings(data.value(licenseTemplatePathKeyC,
|
||||
m_customSettings.licenseTemplatePath.toSettings()));
|
||||
@@ -560,6 +610,7 @@ void CppFileSettingsForProject::saveSettings()
|
||||
data.insert(sourceSearchPathsKeyC, m_customSettings.sourceSearchPaths);
|
||||
data.insert(Constants::LOWERCASE_CPPFILES_KEY, m_customSettings.lowerCaseFiles);
|
||||
data.insert(headerPragmaOnceC, m_customSettings.headerPragmaOnce);
|
||||
data.insert(headerGuardTemplateKeyC, m_customSettings.headerGuardTemplate);
|
||||
data.insert(licenseTemplatePathKeyC, m_customSettings.licenseTemplatePath.toSettings());
|
||||
m_project->setNamedSettings(projectSettingsKeyC, data);
|
||||
}
|
||||
@@ -631,16 +682,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void setupCppFileSettings()
|
||||
{
|
||||
static CppFileSettingsProjectPanelFactory theCppFileSettingsProjectPanelFactory;
|
||||
|
||||
static CppFileSettingsPage theCppFileSettingsPage;
|
||||
|
||||
globalCppFileSettings().fromSettings(Core::ICore::settings());
|
||||
globalCppFileSettings().addMimeInitializer();
|
||||
}
|
||||
|
||||
CppFileSettings &globalCppFileSettings()
|
||||
{
|
||||
// This is the global instance. There could be more.
|
||||
@@ -653,6 +694,59 @@ CppFileSettings cppFileSettingsForProject(ProjectExplorer::Project *project)
|
||||
return CppFileSettingsForProject(project).settings();
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
namespace {
|
||||
class CppFileSettingsTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void testHeaderGuard_data()
|
||||
{
|
||||
QTest::addColumn<QString>("guardTemplate");
|
||||
QTest::addColumn<QString>("headerFile");
|
||||
QTest::addColumn<QString>("expectedGuard");
|
||||
|
||||
QTest::newRow("default template, .h")
|
||||
<< QString() << QString("/tmp/header.h") << QString("HEADER_H");
|
||||
QTest::newRow("default template, .hpp")
|
||||
<< QString() << QString("/tmp/header.hpp") << QString("HEADER_HPP");
|
||||
QTest::newRow("default template, two extensions")
|
||||
<< QString() << QString("/tmp/header.in.h") << QString("HEADER_IN_H");
|
||||
QTest::newRow("non-default template")
|
||||
<< QString("%{JS: '%{Header:FilePath}'.toUpperCase().replace(/[.]/, '_').replace(/[/]/g, '_')}")
|
||||
<< QString("/tmp/header.h") << QString("_TMP_HEADER_H");
|
||||
}
|
||||
|
||||
void testHeaderGuard()
|
||||
{
|
||||
QFETCH(QString, guardTemplate);
|
||||
QFETCH(QString, headerFile);
|
||||
QFETCH(QString, expectedGuard);
|
||||
|
||||
CppFileSettings settings;
|
||||
if (!guardTemplate.isEmpty())
|
||||
settings.headerGuardTemplate = guardTemplate;
|
||||
QCOMPARE(settings.headerGuard(FilePath::fromUserInput(headerFile)), expectedGuard);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
#endif // WITH_TESTS
|
||||
|
||||
void setupCppFileSettings(ExtensionSystem::IPlugin &plugin)
|
||||
{
|
||||
static CppFileSettingsProjectPanelFactory theCppFileSettingsProjectPanelFactory;
|
||||
|
||||
static CppFileSettingsPage theCppFileSettingsPage;
|
||||
|
||||
globalCppFileSettings().fromSettings(Core::ICore::settings());
|
||||
globalCppFileSettings().addMimeInitializer();
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
plugin.addTestCreator([] { return new CppFileSettingsTest; });
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace CppEditor::Internal
|
||||
|
||||
#include <cppfilesettingspage.moc>
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <QDir>
|
||||
|
||||
namespace ExtensionSystem { class IPlugin; }
|
||||
namespace ProjectExplorer { class Project; }
|
||||
|
||||
namespace CppEditor::Internal {
|
||||
@@ -28,6 +29,7 @@ public:
|
||||
QDir::toNativeSeparators("../Src"),
|
||||
".."};
|
||||
Utils::FilePath licenseTemplatePath;
|
||||
QString headerGuardTemplate = "%{JS: '%{Header:FileName}'.toUpperCase().replace(/[.]/g, '_')}";
|
||||
bool headerPragmaOnce = false;
|
||||
bool lowerCaseFiles = Constants::LOWERCASE_CPPFILES_DEFAULT;
|
||||
|
||||
@@ -39,6 +41,9 @@ public:
|
||||
// Convenience to return a license template completely formatted.
|
||||
QString licenseTemplate() const;
|
||||
|
||||
// Expanded headerGuardTemplate.
|
||||
QString headerGuard(const Utils::FilePath &headerFilePath) const;
|
||||
|
||||
bool equals(const CppFileSettings &rhs) const;
|
||||
bool operator==(const CppFileSettings &s) const { return equals(s); }
|
||||
bool operator!=(const CppFileSettings &s) const { return !equals(s); }
|
||||
@@ -48,6 +53,6 @@ CppFileSettings &globalCppFileSettings();
|
||||
|
||||
CppFileSettings cppFileSettingsForProject(ProjectExplorer::Project *project);
|
||||
|
||||
void setupCppFileSettings();
|
||||
void setupCppFileSettings(ExtensionSystem::IPlugin &plugin);
|
||||
|
||||
} // namespace CppEditor::Internal
|
||||
|
@@ -42,7 +42,7 @@ static QString fileName(const QString &path, const QString &extension)
|
||||
|
||||
QString CppToolsJsExtension::headerGuard(const QString &in) const
|
||||
{
|
||||
return Utils::headerGuard(in);
|
||||
return fileSettings().headerGuard(Utils::FilePath::fromString(in));
|
||||
}
|
||||
|
||||
QString CppToolsJsExtension::licenseTemplate() const
|
||||
|
@@ -358,6 +358,11 @@ CppCompletionAssistProcessor *getCppCompletionAssistProcessor()
|
||||
return new Internal::InternalCppCompletionAssistProcessor();
|
||||
}
|
||||
|
||||
QString deriveHeaderGuard(const Utils::FilePath &filePath, ProjectExplorer::Project *project)
|
||||
{
|
||||
return Internal::cppFileSettingsForProject(project).headerGuard(filePath);
|
||||
}
|
||||
|
||||
bool fileSizeExceedsLimit(const FilePath &filePath, int sizeLimitInMb)
|
||||
{
|
||||
if (sizeLimitInMb <= 0)
|
||||
|
@@ -6,7 +6,6 @@
|
||||
#include "cppeditor_global.h"
|
||||
|
||||
#include "clangdiagnosticconfig.h"
|
||||
#include "compileroptionsbuilder.h"
|
||||
#include "projectpart.h"
|
||||
|
||||
#include <texteditor/quickfix.h>
|
||||
@@ -65,6 +64,9 @@ quickFixOperations(const TextEditor::AssistInterface *interface);
|
||||
|
||||
CppCompletionAssistProcessor CPPEDITOR_EXPORT *getCppCompletionAssistProcessor();
|
||||
|
||||
QString CPPEDITOR_EXPORT
|
||||
deriveHeaderGuard(const Utils::FilePath &filePath, ProjectExplorer::Project *project);
|
||||
|
||||
enum class CacheUsage { ReadWrite, ReadOnly };
|
||||
|
||||
Utils::FilePath CPPEDITOR_EXPORT correspondingHeaderOrSource(
|
||||
|
@@ -388,7 +388,7 @@ private:
|
||||
= Utils::transform<QStringList>(state->namespacePath, [&](const Namespace *ns) {
|
||||
return ov.prettyName(ns->name());
|
||||
});
|
||||
const QString headerGuard = Utils::headerGuard(headerFileName);
|
||||
const QString headerGuard = fileSettings.headerGuard(headerFilePath);
|
||||
if (fileSettings.headerPragmaOnce) {
|
||||
headerContent.append("#pragma once\n");
|
||||
} else {
|
||||
|
@@ -27,6 +27,8 @@ const char SHOW_LOG[] = "showLog";
|
||||
const char SHOW_WARNING[] = "showWarning";
|
||||
const char SHOW_ERROR[] = "showError";
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace Debugger::Internal {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@@ -90,8 +92,8 @@ Console::Console()
|
||||
m_showDebug.setLabelText(Tr::tr("Show debug, log, and info messages."));
|
||||
m_showDebug.setToolTip(Tr::tr("Show debug, log, and info messages."));
|
||||
m_showDebug.setValue(true);
|
||||
m_showDebug.action()->setIcon(Utils::Icons::INFO_TOOLBAR.icon());
|
||||
connect(&m_showDebug, &Utils::BoolAspect::changed,
|
||||
m_showDebug.setIcon(Icons::INFO_TOOLBAR.icon());
|
||||
connect(&m_showDebug, &BoolAspect::changed,
|
||||
proxyModel, [this, proxyModel] { proxyModel->setShowLogs(m_showDebug()); });
|
||||
m_showDebugButton->setDefaultAction(m_showDebug.action());
|
||||
|
||||
@@ -102,8 +104,8 @@ Console::Console()
|
||||
m_showWarning.setLabelText(Tr::tr("Show warning messages."));
|
||||
m_showWarning.setToolTip(Tr::tr("Show warning messages."));
|
||||
m_showWarning.setValue(true);
|
||||
m_showWarning.action()->setIcon(Utils::Icons::WARNING_TOOLBAR.icon());
|
||||
connect(m_showWarning.action(), &QAction::toggled,
|
||||
m_showWarning.setIcon(Icons::WARNING_TOOLBAR.icon());
|
||||
connect(&m_showWarning, &BoolAspect::changed,
|
||||
proxyModel, [this, proxyModel] { proxyModel->setShowWarnings(m_showWarning()); });
|
||||
m_showWarningButton->setDefaultAction(m_showWarning.action());
|
||||
|
||||
@@ -114,8 +116,8 @@ Console::Console()
|
||||
m_showError.setLabelText(Tr::tr("Show error messages."));
|
||||
m_showError.setToolTip(Tr::tr("Show error messages."));
|
||||
m_showError.setValue(true);
|
||||
m_showError.action()->setIcon(Utils::Icons::CRITICAL_TOOLBAR.icon());
|
||||
connect(m_showError.action(), &QAction::toggled,
|
||||
m_showError.setIcon(Icons::CRITICAL_TOOLBAR.icon());
|
||||
connect(&m_showError, &BoolAspect::changed,
|
||||
proxyModel, [this, proxyModel] { proxyModel->setShowErrors(m_showError()); });
|
||||
m_showErrorButton->setDefaultAction(m_showError.action());
|
||||
|
||||
|
@@ -125,9 +125,6 @@ public:
|
||||
// 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;
|
||||
|
@@ -440,8 +440,11 @@ static DebuggerItem::MatchLevel matchSingle(const Abi &debuggerAbi, const Abi &t
|
||||
return matchOnMultiarch;
|
||||
}
|
||||
|
||||
if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32)
|
||||
return DebuggerItem::MatchesSomewhat;
|
||||
if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32) {
|
||||
return HostOsInfo::isWindowsHost() && engineType == CdbEngineType
|
||||
? DebuggerItem::MatchesPerfectly
|
||||
: DebuggerItem::MatchesSomewhat;
|
||||
}
|
||||
if (debuggerAbi.wordWidth() != 0 && debuggerAbi.wordWidth() != targetAbi.wordWidth())
|
||||
return matchOnMultiarch;
|
||||
|
||||
|
@@ -783,6 +783,12 @@ void DebuggerItemModel::readDebuggers(const FilePath &fileName, bool isSystem)
|
||||
.arg(item.command().toUserOutput(), item.id().toString(), fileName.toUserOutput());
|
||||
continue;
|
||||
}
|
||||
if (item.engineType() == CdbEngineType
|
||||
&& Abi::abisOfBinary(item.command()).value(0).wordWidth() == 32) {
|
||||
qWarning() << QString("32 bit CDB \"%1\" (%2) read from \"%3\" dropped since it is not supported anymore.")
|
||||
.arg(item.command().toUserOutput(), item.id().toString(), fileName.toUserOutput());
|
||||
continue;
|
||||
}
|
||||
// FIXME: During startup, devices are not yet available, so we cannot check if the file still exists.
|
||||
if (!item.command().needsDevice() && !item.command().isExecutableFile()) {
|
||||
qWarning() << QString("DebuggerItem \"%1\" (%2) read from \"%3\" dropped since the command is not executable.")
|
||||
|
@@ -388,6 +388,15 @@ public:
|
||||
k->setValue(DebuggerKitAspect::id(), bestLevel != DebuggerItem::DoesNotMatch ? bestItem.id() : QVariant());
|
||||
}
|
||||
|
||||
void fix(Kit *k) override
|
||||
{
|
||||
const QVariant id = k->value(DebuggerKitAspect::id());
|
||||
if (Utils::anyOf(DebuggerItemManager::debuggers(), Utils::equal(&DebuggerItem::id, id)))
|
||||
return;
|
||||
k->removeKeySilently(DebuggerKitAspect::id());
|
||||
setup(k);
|
||||
}
|
||||
|
||||
KitAspect *createKitAspect(Kit *k) const override
|
||||
{
|
||||
return new Internal::DebuggerKitAspectImpl(k, this);
|
||||
|
@@ -276,11 +276,6 @@ 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;
|
||||
|
@@ -100,7 +100,6 @@ protected:
|
||||
void setRemoteChannel(const QUrl &url);
|
||||
void setUseTargetAsync(bool on);
|
||||
void setSkipExecutableValidation(bool on);
|
||||
void setUseCtrlCStub(bool on);
|
||||
|
||||
void setIosPlatform(const QString &platform);
|
||||
void setDeviceSymbolsRoot(const QString &deviceSymbolsRoot);
|
||||
|
@@ -124,6 +124,7 @@ const char notCompatibleMessage[] = "is not compatible with target architecture"
|
||||
GdbEngine::GdbEngine()
|
||||
{
|
||||
m_gdbProc.setProcessMode(ProcessMode::Writer);
|
||||
m_gdbProc.setUseCtrlCStub(true);
|
||||
|
||||
setObjectName("GdbEngine");
|
||||
setDebuggerName("GDB");
|
||||
@@ -673,26 +674,7 @@ void GdbEngine::interruptInferior()
|
||||
} else {
|
||||
showStatusMessage(Tr::tr("Stop requested..."), 5000);
|
||||
showMessage("TRYING TO INTERRUPT INFERIOR");
|
||||
if (HostOsInfo::isWindowsHost() && !m_isQnxGdb) {
|
||||
IDevice::ConstPtr dev = device();
|
||||
QTC_ASSERT(dev, notifyInferiorStopFailed(); return);
|
||||
DeviceProcessSignalOperation::Ptr signalOperation = dev->signalOperation();
|
||||
QTC_ASSERT(signalOperation, notifyInferiorStopFailed(); return);
|
||||
connect(signalOperation.get(), &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.command.executable());
|
||||
signalOperation->interruptProcess(inferiorPid());
|
||||
} else {
|
||||
interruptInferior2();
|
||||
}
|
||||
interruptInferior2();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1265,9 +1247,11 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
||||
handleStop1(data);
|
||||
}
|
||||
|
||||
static QString stopSignal(const Abi &abi)
|
||||
static QStringList stopSignals(const Abi &abi)
|
||||
{
|
||||
return QLatin1String(abi.os() == Abi::WindowsOS ? "SIGTRAP" : "SIGINT");
|
||||
static QStringList winSignals = { "SIGTRAP", "SIGINT" };
|
||||
static QStringList unixSignals = { "SIGINT" };
|
||||
return abi.os() == Abi::WindowsOS ? winSignals : unixSignals;
|
||||
}
|
||||
|
||||
void GdbEngine::handleStop1(const GdbMi &data)
|
||||
@@ -1416,7 +1400,7 @@ void GdbEngine::handleStop2(const GdbMi &data)
|
||||
QString meaning = data["signal-meaning"].data();
|
||||
// Ignore these as they are showing up regularly when
|
||||
// stopping debugging.
|
||||
if (name == stopSignal(rp.toolChainAbi) || rp.expectedSignals.contains(name)) {
|
||||
if (stopSignals(rp.toolChainAbi).contains(name) || rp.expectedSignals.contains(name)) {
|
||||
showMessage(name + " CONSIDERED HARMLESS. CONTINUING.");
|
||||
} else if (m_isQnxGdb && name == "0" && meaning == "Signal 0") {
|
||||
showMessage("SIGNAL 0 CONSIDERED BOGUS.");
|
||||
@@ -3817,9 +3801,6 @@ void GdbEngine::setupEngine()
|
||||
CHECK_STATE(EngineSetupRequested);
|
||||
showMessage("TRYING TO START ADAPTER");
|
||||
|
||||
if (isRemoteEngine())
|
||||
m_gdbProc.setUseCtrlCStub(runParameters().useCtrlCStub); // This is only set for QNX
|
||||
|
||||
const DebuggerRunParameters &rp = runParameters();
|
||||
CommandLine gdbCommand = rp.debugger.command;
|
||||
|
||||
@@ -4314,7 +4295,6 @@ void GdbEngine::interruptLocalInferior(qint64 pid)
|
||||
showMessage("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED", LogError);
|
||||
return;
|
||||
}
|
||||
QString errorMessage;
|
||||
if (runParameters().runAsRoot) {
|
||||
Environment env = Environment::systemEnvironment();
|
||||
RunControl::provideAskPassEntry(env);
|
||||
@@ -4323,11 +4303,8 @@ void GdbEngine::interruptLocalInferior(qint64 pid)
|
||||
proc.setEnvironment(env);
|
||||
proc.start();
|
||||
proc.waitForFinished();
|
||||
} else if (interruptProcess(pid, GdbEngineType, &errorMessage)) {
|
||||
showMessage("Interrupted " + QString::number(pid));
|
||||
} else {
|
||||
showMessage(errorMessage, LogError);
|
||||
notifyInferiorStopFailed();
|
||||
m_gdbProc.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -143,7 +143,7 @@ void PdbEngine::handlePdbStarted()
|
||||
void PdbEngine::interruptInferior()
|
||||
{
|
||||
QString error;
|
||||
interruptProcess(m_proc.processId(), GdbEngineType, &error);
|
||||
interruptProcess(m_proc.processId(), &error);
|
||||
}
|
||||
|
||||
void PdbEngine::executeStepIn(bool)
|
||||
|
@@ -23,128 +23,23 @@ static inline QString msgCannotInterrupt(qint64 pid, const QString &why)
|
||||
# define PROCESS_SUSPEND_RESUME (0x0800)
|
||||
#endif // PROCESS_SUSPEND_RESUME
|
||||
|
||||
static BOOL isWow64Process(HANDLE hproc)
|
||||
{
|
||||
using LPFN_ISWOW64PROCESS = BOOL (WINAPI*)(HANDLE, PBOOL);
|
||||
|
||||
BOOL ret = false;
|
||||
|
||||
static LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
|
||||
if (!fnIsWow64Process) {
|
||||
if (HMODULE hModule = GetModuleHandle(L"kernel32.dll"))
|
||||
fnIsWow64Process = reinterpret_cast<LPFN_ISWOW64PROCESS>(GetProcAddress(hModule, "IsWow64Process"));
|
||||
}
|
||||
|
||||
if (!fnIsWow64Process) {
|
||||
qWarning("Cannot retrieve symbol 'IsWow64Process'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fnIsWow64Process(hproc, &ret)) {
|
||||
qWarning("IsWow64Process() failed for %p: %s",
|
||||
hproc, qPrintable(Utils::winErrorMessage(GetLastError())));
|
||||
return false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Open the process and break into it
|
||||
bool Debugger::Internal::interruptProcess(qint64 pID, int engineType, QString *errorMessage, const bool engineExecutableIs64Bit)
|
||||
bool Debugger::Internal::interruptProcess(qint64 pID, QString *errorMessage)
|
||||
{
|
||||
bool ok = false;
|
||||
HANDLE inferior = NULL;
|
||||
do {
|
||||
const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
|
||||
|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
|
||||
|PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
|
||||
inferior = OpenProcess(rights, FALSE, DWORD(pID));
|
||||
if (inferior == NULL) {
|
||||
*errorMessage = QString::fromLatin1("Cannot open process %1: %2").
|
||||
arg(pID).arg(Utils::winErrorMessage(GetLastError()));
|
||||
break;
|
||||
}
|
||||
const DWORD rights = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION | PROCESS_VM_OPERATION
|
||||
| PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_DUP_HANDLE
|
||||
| PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_SUSPEND_RESUME;
|
||||
inferior = OpenProcess(rights, FALSE, DWORD(pID));
|
||||
if (inferior == NULL) {
|
||||
*errorMessage = QString::fromLatin1("Cannot open process %1: %2")
|
||||
.arg(pID)
|
||||
.arg(Utils::winErrorMessage(GetLastError()));
|
||||
} else if (ok = DebugBreakProcess(inferior); !ok) {
|
||||
*errorMessage = "DebugBreakProcess failed: " + Utils::winErrorMessage(GetLastError());
|
||||
}
|
||||
|
||||
enum DebugBreakApi {
|
||||
UseDebugBreakApi,
|
||||
UseWin64Interrupt,
|
||||
UseWin32Interrupt
|
||||
};
|
||||
/*
|
||||
Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a
|
||||
32 bit application inside a 64 bit environment.
|
||||
When GDB is used DebugBreakProcess must be called from the same system (32/64 bit) running
|
||||
the inferior. If CDB is used we could in theory break wow64 processes,
|
||||
but the break is actually a wow64 breakpoint. CDB is configured to ignore these
|
||||
breakpoints, because they also appear on module loading.
|
||||
Therefore we need helper executables (win(32/64)interrupt.exe) on Windows 64 bit calling
|
||||
DebugBreakProcess from the correct system.
|
||||
|
||||
DebugBreak matrix for windows
|
||||
|
||||
Api = UseDebugBreakApi
|
||||
Win64 = UseWin64Interrupt
|
||||
Win32 = UseWin32Interrupt
|
||||
N/A = This configuration is not possible
|
||||
|
||||
| Windows 32bit | Windows 64bit
|
||||
| QtCreator 32bit | QtCreator 32bit | QtCreator 64bit
|
||||
| Inferior 32bit | Inferior 32bit | Inferior 64bit | Inferior 32bit | Inferior 64bit |
|
||||
----------|-----------------|-----------------|-----------------|-----------------|----------------|
|
||||
CDB 32bit | Api | Api | NA | Win32 | NA |
|
||||
64bit | NA | Win64 | Win64 | Api | Api |
|
||||
----------|-----------------|-----------------|-----------------|-----------------|----------------|
|
||||
GDB 32bit | Api | Api | NA | Win32 | NA |
|
||||
64bit | NA | Api | Win64 | Win32 | Api |
|
||||
----------|-----------------|-----------------|-----------------|-----------------|----------------|
|
||||
|
||||
*/
|
||||
|
||||
DebugBreakApi breakApi = UseDebugBreakApi;
|
||||
#ifdef Q_OS_WIN64
|
||||
if ((engineType == GdbEngineType && isWow64Process(inferior))
|
||||
|| (engineType == CdbEngineType && !engineExecutableIs64Bit)) {
|
||||
breakApi = UseWin32Interrupt;
|
||||
}
|
||||
#else
|
||||
if (isWow64Process(GetCurrentProcess())
|
||||
&& ((engineType == CdbEngineType && engineExecutableIs64Bit)
|
||||
|| (engineType == GdbEngineType && !isWow64Process(inferior)))) {
|
||||
breakApi = UseWin64Interrupt;
|
||||
}
|
||||
#endif
|
||||
if (breakApi == UseDebugBreakApi) {
|
||||
ok = DebugBreakProcess(inferior);
|
||||
if (!ok)
|
||||
*errorMessage = "DebugBreakProcess failed: " + Utils::winErrorMessage(GetLastError());
|
||||
} else {
|
||||
const QString executable = breakApi == UseWin32Interrupt
|
||||
? QCoreApplication::applicationDirPath() + "/win32interrupt.exe"
|
||||
: QCoreApplication::applicationDirPath() + "/win64interrupt.exe";
|
||||
if (!QFileInfo::exists(executable)) {
|
||||
*errorMessage = QString::fromLatin1(
|
||||
"%1 does not exist. If you have built %2 "
|
||||
"on your own, checkout "
|
||||
"https://code.qt.io/cgit/qt-creator/binary-artifacts.git/.")
|
||||
.arg(QDir::toNativeSeparators(executable),
|
||||
QGuiApplication::applicationDisplayName());
|
||||
break;
|
||||
}
|
||||
switch (QProcess::execute(executable, QStringList(QString::number(pID)))) {
|
||||
case -2:
|
||||
*errorMessage = QString::fromLatin1("Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c for more information.").
|
||||
arg(QDir::toNativeSeparators(executable));
|
||||
break;
|
||||
case 0:
|
||||
ok = true;
|
||||
break;
|
||||
default:
|
||||
*errorMessage = QDir::toNativeSeparators(executable)
|
||||
+ " could not break the process.";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (false);
|
||||
if (inferior != NULL)
|
||||
CloseHandle(inferior);
|
||||
if (!ok)
|
||||
@@ -159,8 +54,7 @@ GDB 32bit | Api | Api | NA | Win32
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
bool Debugger::Internal::interruptProcess(qint64 pID, int /* engineType */,
|
||||
QString *errorMessage, const bool /*engineExecutableIs64Bit*/)
|
||||
bool Debugger::Internal::interruptProcess(qint64 pID, QString *errorMessage)
|
||||
{
|
||||
if (pID <= 0) {
|
||||
*errorMessage = msgCannotInterrupt(pID, QString::fromLatin1("Invalid process id."));
|
||||
|
@@ -7,7 +7,6 @@
|
||||
|
||||
namespace Debugger::Internal {
|
||||
|
||||
bool interruptProcess(qint64 pID, int engineType, QString *errorMessage,
|
||||
const bool engineExecutableIs64Bit = false);
|
||||
bool interruptProcess(qint64 pID, QString *errorMessage);
|
||||
|
||||
} // Debugger::Internal
|
||||
|
@@ -904,7 +904,7 @@ static ConsoleItem *constructLogItemTree(const QVariant &result, const QString &
|
||||
if (child)
|
||||
item->appendChild(child);
|
||||
}
|
||||
} else if (result.canConvert(QMetaType::QString)) {
|
||||
} else if (result.canConvert(QMetaType(QMetaType::QString))) {
|
||||
item = new ConsoleItem(ConsoleItem::DefaultType, result.toString());
|
||||
} else {
|
||||
item = new ConsoleItem(ConsoleItem::DefaultType, "Unknown Value");
|
||||
|
@@ -25,7 +25,7 @@ else()
|
||||
endif()
|
||||
|
||||
add_qtc_plugin(Designer
|
||||
PLUGIN_CLASS FormEditorPlugin
|
||||
PLUGIN_CLASS DesignerPlugin
|
||||
CONDITION TARGET Qt::DesignerComponentsPrivate AND TARGET Qt::Designer
|
||||
DEPENDS designerintegrationv2
|
||||
Qt::Designer Qt::PrintSupport Qt::DesignerComponentsPrivate
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <cppeditor/abstracteditorsupport.h>
|
||||
#include <cppeditor/cpptoolsreuse.h>
|
||||
#include <projectexplorer/projecttree.h>
|
||||
#include <qtsupport/codegenerator.h>
|
||||
#include <qtsupport/codegensettings.h>
|
||||
@@ -75,7 +76,8 @@ bool QtDesignerFormClassCodeGenerator::generateCpp(const FormClassWizardParamete
|
||||
const QString sourceLicense = CppEditor::AbstractEditorSupport::licenseTemplate(
|
||||
project, FilePath::fromString(parameters.sourceFile), parameters.className);
|
||||
// Include guards
|
||||
const QString guard = Utils::headerGuard(parameters.headerFile);
|
||||
const QString guard
|
||||
= CppEditor::deriveHeaderGuard(FilePath::fromString(parameters.headerFile), project);
|
||||
|
||||
const QString uiInclude = "ui_" + QFileInfo(parameters.uiFile).completeBaseName() + ".h";
|
||||
|
||||
|
@@ -39,9 +39,9 @@ QString EffectComposerContextObject::convertColorToString(const QVariant &color)
|
||||
{
|
||||
QString colorString;
|
||||
QColor theColor;
|
||||
if (color.canConvert(QVariant::Color)) {
|
||||
if (color.canConvert(QMetaType(QMetaType::QColor))) {
|
||||
theColor = color.value<QColor>();
|
||||
} else if (color.canConvert(QVariant::Vector3D)) {
|
||||
} else if (color.canConvert(QMetaType(QMetaType::QVector3D))) {
|
||||
auto vec = color.value<QVector3D>();
|
||||
theColor = QColor::fromRgbF(vec.x(), vec.y(), vec.z());
|
||||
}
|
||||
|
@@ -548,6 +548,13 @@ static void registerLuaApi()
|
||||
// ... then register the settings.
|
||||
LanguageClientManager::registerClientSettings(client);
|
||||
|
||||
// and the client type.
|
||||
ClientType type;
|
||||
type.id = client->m_settingsTypeId;
|
||||
type.name = luaClient->m_name;
|
||||
type.userAddable = false;
|
||||
LanguageClientSettings::registerClientType(type);
|
||||
|
||||
return luaClient;
|
||||
});
|
||||
|
||||
|
@@ -1,4 +1,6 @@
|
||||
{
|
||||
"$schema": "https://download.qt.io/official_releases/qtcreator/latest/installer_source/jsonschemas/project.json",
|
||||
"files.exclude": [".qtcreator/project.json.user"],
|
||||
"targets": [
|
||||
{
|
||||
"name": "Qt Creator",
|
||||
|
@@ -78,7 +78,7 @@ public:
|
||||
const QVariant checkFormat = kit->value(McuDependenciesKitAspect::id());
|
||||
if (!checkFormat.isValid() || checkFormat.isNull())
|
||||
return result;
|
||||
if (!checkFormat.canConvert(QMetaType::QVariantList))
|
||||
if (!checkFormat.canConvert(QMetaType(QMetaType::QVariantList)))
|
||||
return {BuildSystemTask(Task::Error, Tr::tr("The MCU dependencies setting value is invalid."))};
|
||||
|
||||
// check paths defined in cmake variables for given dependencies exist
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
QTC_ASSERT(kit, return );
|
||||
|
||||
const QVariant variant = kit->value(McuDependenciesKitAspect::id());
|
||||
if (!variant.isNull() && !variant.canConvert(QMetaType::QVariantList)) {
|
||||
if (!variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList))) {
|
||||
qWarning("Kit \"%s\" has a wrong mcu dependencies value set.",
|
||||
qPrintable(kit->displayName()));
|
||||
McuDependenciesKitAspect::setDependencies(kit, Utils::EnvironmentItems());
|
||||
|
@@ -102,90 +102,20 @@ void DesktopProcessSignalOperation::killProcessSilently(qint64 pid)
|
||||
void DesktopProcessSignalOperation::interruptProcessSilently(qint64 pid)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
enum SpecialInterrupt { NoSpecialInterrupt, Win32Interrupt, Win64Interrupt };
|
||||
|
||||
bool is64BitSystem = is64BitWindowsSystem();
|
||||
SpecialInterrupt si = NoSpecialInterrupt;
|
||||
if (is64BitSystem)
|
||||
si = is64BitWindowsBinary(m_debuggerCommand) ? Win64Interrupt : Win32Interrupt;
|
||||
/*
|
||||
Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a
|
||||
32 bit application inside a 64 bit environment.
|
||||
When GDB is used DebugBreakProcess must be called from the same system (32/64 bit) running
|
||||
the inferior. If CDB is used we could in theory break wow64 processes,
|
||||
but the break is actually a wow64 breakpoint. CDB is configured to ignore these
|
||||
breakpoints, because they also appear on module loading.
|
||||
Therefore we need helper executables (win(32/64)interrupt.exe) on Windows 64 bit calling
|
||||
DebugBreakProcess from the correct system.
|
||||
|
||||
DebugBreak matrix for windows
|
||||
|
||||
Api = UseDebugBreakApi
|
||||
Win64 = UseWin64InterruptHelper
|
||||
Win32 = UseWin32InterruptHelper
|
||||
N/A = This configuration is not possible
|
||||
|
||||
| Windows 32bit | Windows 64bit
|
||||
| QtCreator 32bit | QtCreator 32bit | QtCreator 64bit
|
||||
| Inferior 32bit | Inferior 32bit | Inferior 64bit | Inferior 32bit | Inferior 64bit
|
||||
----------|-----------------|-----------------|-----------------|-----------------|----------------
|
||||
CDB 32bit | Api | Api | N/A | Win32 | N/A
|
||||
64bit | N/A | Win64 | Win64 | Api | Api
|
||||
----------|-----------------|-----------------|-----------------|-----------------|----------------
|
||||
GDB 32bit | Api | Api | N/A | Win32 | N/A
|
||||
64bit | N/A | N/A | Win64 | N/A | Api
|
||||
----------|-----------------|-----------------|-----------------|-----------------|----------------
|
||||
|
||||
*/
|
||||
HANDLE inferior = NULL;
|
||||
do {
|
||||
const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
|
||||
|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
|
||||
|PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
|
||||
inferior = OpenProcess(rights, FALSE, pid);
|
||||
if (inferior == NULL) {
|
||||
appendMsgCannotInterrupt(pid, Tr::tr("Cannot open process: %1")
|
||||
+ winErrorMessage(GetLastError()));
|
||||
break;
|
||||
}
|
||||
bool creatorIs64Bit = is64BitWindowsBinary(
|
||||
FilePath::fromUserInput(QCoreApplication::applicationFilePath()));
|
||||
if (!is64BitSystem
|
||||
|| si == NoSpecialInterrupt
|
||||
|| (si == Win64Interrupt && creatorIs64Bit)
|
||||
|| (si == Win32Interrupt && !creatorIs64Bit)) {
|
||||
if (!DebugBreakProcess(inferior)) {
|
||||
appendMsgCannotInterrupt(pid, Tr::tr("DebugBreakProcess failed:")
|
||||
+ QLatin1Char(' ') + winErrorMessage(GetLastError()));
|
||||
}
|
||||
} else if (si == Win32Interrupt || si == Win64Interrupt) {
|
||||
QString executable = QCoreApplication::applicationDirPath();
|
||||
executable += si == Win32Interrupt
|
||||
? QLatin1String("/win32interrupt.exe")
|
||||
: QLatin1String("/win64interrupt.exe");
|
||||
if (!QFileInfo::exists(executable)) {
|
||||
appendMsgCannotInterrupt(pid,
|
||||
Tr::tr("%1 does not exist. If you built %2 "
|
||||
"yourself, check out https://code.qt.io/cgit/"
|
||||
"qt-creator/binary-artifacts.git/.")
|
||||
.arg(QDir::toNativeSeparators(executable),
|
||||
QGuiApplication::applicationDisplayName()));
|
||||
}
|
||||
switch (QProcess::execute(executable, QStringList(QString::number(pid)))) {
|
||||
case -2:
|
||||
appendMsgCannotInterrupt(pid, Tr::tr(
|
||||
"Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c "
|
||||
"for more information.").arg(QDir::toNativeSeparators(executable)));
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
appendMsgCannotInterrupt(pid, QDir::toNativeSeparators(executable)
|
||||
+ QLatin1Char(' ') + Tr::tr("could not break the process."));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (false);
|
||||
const DWORD rights = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION | PROCESS_VM_OPERATION
|
||||
| PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_DUP_HANDLE
|
||||
| PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_SUSPEND_RESUME;
|
||||
inferior = OpenProcess(rights, FALSE, pid);
|
||||
if (inferior == NULL) {
|
||||
appendMsgCannotInterrupt(
|
||||
pid, Tr::tr("Cannot open process: %1") + winErrorMessage(GetLastError()));
|
||||
} else if (!DebugBreakProcess(inferior)) {
|
||||
appendMsgCannotInterrupt(
|
||||
pid,
|
||||
Tr::tr("DebugBreakProcess failed:") + QLatin1Char(' ')
|
||||
+ winErrorMessage(GetLastError()));
|
||||
}
|
||||
if (inferior != NULL)
|
||||
CloseHandle(inferior);
|
||||
#else
|
||||
|
@@ -1539,7 +1539,7 @@ Tasks EnvironmentKitAspectFactory::validate(const Kit *k) const
|
||||
QTC_ASSERT(k, return result);
|
||||
|
||||
const QVariant variant = k->value(EnvironmentKitAspect::id());
|
||||
if (!variant.isNull() && !variant.canConvert(QMetaType::QVariantList))
|
||||
if (!variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList)))
|
||||
result << BuildSystemTask(Task::Error, Tr::tr("The environment setting value is invalid."));
|
||||
|
||||
return result;
|
||||
@@ -1550,7 +1550,7 @@ void EnvironmentKitAspectFactory::fix(Kit *k)
|
||||
QTC_ASSERT(k, return);
|
||||
|
||||
const QVariant variant = k->value(EnvironmentKitAspect::id());
|
||||
if (!variant.isNull() && !variant.canConvert(QMetaType::QVariantList)) {
|
||||
if (!variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList))) {
|
||||
qWarning("Kit \"%s\" has a wrong environment value set.", qPrintable(k->displayName()));
|
||||
EnvironmentKitAspect::setEnvironmentChanges(k, EnvironmentItems());
|
||||
}
|
||||
|
@@ -253,7 +253,12 @@ public:
|
||||
: Project(FOLDER_MIMETYPE, file.isDir() ? file / ".qtcreator" / "project.json" : file)
|
||||
{
|
||||
QTC_CHECK(projectFilePath().absolutePath().ensureWritableDir());
|
||||
QTC_CHECK(projectFilePath().ensureExistingFile());
|
||||
if (!projectFilePath().exists() && QTC_GUARD(projectFilePath().ensureExistingFile())) {
|
||||
QJsonObject projectJson;
|
||||
projectJson.insert("$schema", "https://download.qt.io/official_releases/qtcreator/latest/installer_source/jsonschemas/project.json");
|
||||
projectJson.insert(FILES_EXCLUDE_KEY, QJsonArray{QJsonValue(".qtcreator/project.json.user")});
|
||||
projectFilePath().writeFileContents(QJsonDocument(projectJson).toJson());
|
||||
}
|
||||
|
||||
setId(Id::fromString(WORKSPACE_PROJECT_ID));
|
||||
setDisplayName(projectDirectory().fileName());
|
||||
|
@@ -46,9 +46,9 @@ QString MaterialEditorContextObject::convertColorToString(const QVariant &color)
|
||||
{
|
||||
QString colorString;
|
||||
QColor theColor;
|
||||
if (color.canConvert(QVariant::Color)) {
|
||||
if (color.canConvert(QMetaType(QMetaType::QColor))) {
|
||||
theColor = color.value<QColor>();
|
||||
} else if (color.canConvert(QVariant::Vector3D)) {
|
||||
} else if (color.canConvert(QMetaType(QMetaType::QVector3D))) {
|
||||
auto vec = color.value<QVector3D>();
|
||||
theColor = QColor::fromRgbF(vec.x(), vec.y(), vec.z());
|
||||
}
|
||||
|
@@ -87,9 +87,9 @@ QString PropertyEditorContextObject::convertColorToString(const QVariant &color)
|
||||
{
|
||||
QString colorString;
|
||||
QColor theColor;
|
||||
if (color.canConvert(QVariant::Color)) {
|
||||
if (color.canConvert(QMetaType(QMetaType::QColor))) {
|
||||
theColor = color.value<QColor>();
|
||||
} else if (color.canConvert(QVariant::Vector3D)) {
|
||||
} else if (color.canConvert(QMetaType(QMetaType::QVector3D))) {
|
||||
auto vec = color.value<QVector3D>();
|
||||
theColor = QColor::fromRgbF(vec.x(), vec.y(), vec.z());
|
||||
}
|
||||
|
@@ -47,9 +47,9 @@ QString TextureEditorContextObject::convertColorToString(const QVariant &color)
|
||||
{
|
||||
QString colorString;
|
||||
QColor theColor;
|
||||
if (color.canConvert(QVariant::Color)) {
|
||||
if (color.canConvert(QMetaType(QMetaType::QColor))) {
|
||||
theColor = color.value<QColor>();
|
||||
} else if (color.canConvert(QVariant::Vector3D)) {
|
||||
} else if (color.canConvert(QMetaType(QMetaType::QVector3D))) {
|
||||
auto vec = color.value<QVector3D>();
|
||||
theColor = QColor::fromRgbF(vec.x(), vec.y(), vec.z());
|
||||
}
|
||||
|
@@ -107,14 +107,14 @@ static void editValue(const ModelNode &frameNode, const std::pair<qreal, qreal>
|
||||
int userType = value.typeId();
|
||||
QVariant newValue = dialog->value();
|
||||
|
||||
if (newValue.canConvert(userType)) {
|
||||
if (newValue.canConvert(QMetaType(userType))) {
|
||||
QVariant newValueConverted = newValue;
|
||||
bool converted = newValueConverted.convert(userType);
|
||||
bool converted = newValueConverted.convert(QMetaType(userType));
|
||||
|
||||
if (!converted) {
|
||||
// convert() fails for int to double, so we try this combination
|
||||
newValueConverted = newValue;
|
||||
converted = newValueConverted.convert(QMetaType::Double);
|
||||
converted = newValueConverted.convert(QMetaType(QMetaType::Double));
|
||||
}
|
||||
|
||||
if (converted)
|
||||
|
@@ -1565,7 +1565,7 @@ void TextToModelMerger::syncVariantProperty(AbstractProperty &modelProperty,
|
||||
const TypeName &astType,
|
||||
DifferenceHandler &differenceHandler)
|
||||
{
|
||||
if (astValue.canConvert(QMetaType::QString))
|
||||
if (astValue.canConvert(QMetaType(QMetaType::QString)))
|
||||
populateQrcMapping(astValue.toString());
|
||||
|
||||
if (modelProperty.isVariantProperty()) {
|
||||
|
@@ -126,7 +126,6 @@ public:
|
||||
|
||||
setStartMode(AttachToRemoteServer);
|
||||
setCloseMode(KillAtClose);
|
||||
setUseCtrlCStub(true);
|
||||
setSolibSearchPath(FileUtils::toFilePathList(searchPaths(k)));
|
||||
if (auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitAspect::qtVersion(k))) {
|
||||
setSysRoot(qtVersion->qnxTarget());
|
||||
@@ -196,7 +195,6 @@ public:
|
||||
{
|
||||
setId("QnxAttachDebugSupport");
|
||||
setUsePortsGatherer(isCppDebugging(), isQmlDebugging());
|
||||
setUseCtrlCStub(true);
|
||||
|
||||
if (isCppDebugging()) {
|
||||
auto pdebugRunner = new PDebugRunner(runControl, portsGatherer());
|
||||
|
@@ -4,6 +4,7 @@ add_qtc_plugin(QtApplicationManagerIntegration
|
||||
PLUGIN_DEPENDS
|
||||
Core Debugger ProjectExplorer
|
||||
QtSupport RemoteLinux
|
||||
PLUGIN_CLASS AppManagerPlugin
|
||||
DEPENDS Qt::Network Qt::Widgets ExtensionSystem Utils yaml-cpp
|
||||
SOURCES
|
||||
appmanagerconstants.h
|
||||
|
@@ -110,6 +110,21 @@ public:
|
||||
m_textEditorWidget->setTextDocument(m_document);
|
||||
m_textEditorWidget->setupGenericHighlighter();
|
||||
m_textEditorWidget->setMarksVisible(false);
|
||||
QObject::connect(
|
||||
m_textEditorWidget,
|
||||
&TextEditorWidget::saveCurrentStateForNavigationHistory,
|
||||
this,
|
||||
&MarkdownEditor::saveCurrentStateForNavigationHistory);
|
||||
QObject::connect(
|
||||
m_textEditorWidget,
|
||||
&TextEditorWidget::addSavedStateToNavigationHistory,
|
||||
this,
|
||||
&MarkdownEditor::addSavedStateToNavigationHistory);
|
||||
QObject::connect(
|
||||
m_textEditorWidget,
|
||||
&TextEditorWidget::addCurrentStateToNavigationHistory,
|
||||
this,
|
||||
&MarkdownEditor::addCurrentStateToNavigationHistory);
|
||||
auto context = new IContext(this);
|
||||
context->setWidget(m_textEditorWidget);
|
||||
context->setContext(Context(MARKDOWNVIEWER_TEXT_CONTEXT));
|
||||
@@ -476,6 +491,18 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void saveCurrentStateForNavigationHistory() { m_savedNavigationState = saveState(); }
|
||||
|
||||
void addSavedStateToNavigationHistory()
|
||||
{
|
||||
EditorManager::addCurrentPositionToNavigationHistory(m_savedNavigationState);
|
||||
}
|
||||
|
||||
void addCurrentStateToNavigationHistory()
|
||||
{
|
||||
EditorManager::addCurrentPositionToNavigationHistory();
|
||||
}
|
||||
|
||||
private:
|
||||
QTimer m_previewTimer;
|
||||
bool m_performDelayedUpdate = false;
|
||||
@@ -491,6 +518,7 @@ private:
|
||||
QAction *m_togglePreviewVisibleAction;
|
||||
QAction *m_swapViewsAction;
|
||||
std::optional<QPoint> m_previewRestoreScrollPosition;
|
||||
QByteArray m_savedNavigationState;
|
||||
};
|
||||
|
||||
class MarkdownEditorFactory final : public IEditorFactory
|
||||
|
Reference in New Issue
Block a user