forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/6.0'
Conflicts: cmake/QtCreatorIDEBranding.cmake qbs/modules/qtc/qtc.qbs qtcreator_ide_branding.pri Change-Id: Id5e67457e2c8c96cfcd29fb5469b6650ec7bcc94
This commit is contained in:
2
.github/workflows/build_cmake.yml
vendored
2
.github/workflows/build_cmake.yml
vendored
@@ -3,7 +3,7 @@ name: CMake Build Matrix
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
QT_VERSION: 6.2.0
|
||||
QT_VERSION: 6.2.1
|
||||
CLANG_VERSION: 130
|
||||
ELFUTILS_VERSION: 0.175
|
||||
CMAKE_VERSION: 3.21.1
|
||||
|
@@ -164,13 +164,13 @@ def fix_rpaths(path, qt_deploy_path, qt_install_info, chrpath=None):
|
||||
if len(rpath) <= 0:
|
||||
return
|
||||
# remove previous Qt RPATH
|
||||
new_rpath = list(filter(lambda path: not path.startswith(qt_install_prefix) and not path.startswith(qt_install_libs),
|
||||
rpath))
|
||||
new_rpath = [path for path in rpath if not path.startswith(qt_install_prefix)
|
||||
and not path.startswith(qt_install_libs)]
|
||||
|
||||
# check for Qt linking
|
||||
lddOutput = subprocess.check_output(['ldd', filepath])
|
||||
lddDecodedOutput = lddOutput.decode(encoding) if encoding else lddOutput
|
||||
if lddDecodedOutput.find('libQt5') >= 0 or lddDecodedOutput.find('libicu') >= 0:
|
||||
if lddDecodedOutput.find('libQt') >= 0 or lddDecodedOutput.find('libicu') >= 0:
|
||||
# add Qt RPATH if necessary
|
||||
relative_path = os.path.relpath(qt_deploy_path, os.path.dirname(filepath))
|
||||
if relative_path == '.':
|
||||
|
@@ -1137,6 +1137,7 @@ class DumperBase():
|
||||
'char',
|
||||
'wchar_t',
|
||||
'unsigned char',
|
||||
'uint8_t',
|
||||
'signed char',
|
||||
'CHAR',
|
||||
'WCHAR'
|
||||
@@ -1243,7 +1244,7 @@ class DumperBase():
|
||||
if innerType.code == TypeCode.Typedef:
|
||||
targetType = innerType.ltarget
|
||||
|
||||
if targetType.name in ('char', 'signed char', 'unsigned char', 'CHAR'):
|
||||
if targetType.name in ('char', 'signed char', 'unsigned char', 'uint8_t', 'CHAR'):
|
||||
# Use UTF-8 as default for char *.
|
||||
self.putType(typeName)
|
||||
(elided, shown, data) = self.readToFirstZero(ptr, 1, limit)
|
||||
@@ -1406,6 +1407,7 @@ class DumperBase():
|
||||
'char',
|
||||
'signed char',
|
||||
'unsigned char',
|
||||
'uint8_t',
|
||||
'wchar_t',
|
||||
'CHAR',
|
||||
'WCHAR'
|
||||
@@ -3628,6 +3630,7 @@ class DumperBase():
|
||||
'char': 'int:1',
|
||||
'signed char': 'int:1',
|
||||
'unsigned char': 'uint:1',
|
||||
'uint8_t': 'uint:1',
|
||||
'short': 'int:2',
|
||||
'unsigned short': 'uint:2',
|
||||
'int': 'int:4',
|
||||
|
@@ -140,25 +140,6 @@ Section {
|
||||
ExpandingSpacer {}
|
||||
}
|
||||
|
||||
PropertyLabel {
|
||||
text: qsTr("Weight")
|
||||
tooltip: qsTr("Font's weight.")
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
ComboBox {
|
||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||
+ StudioTheme.Values.actionIndicatorWidth
|
||||
width: implicitWidth
|
||||
backendValue: getBackendValue("weight")
|
||||
model: ["Normal", "Light", "ExtraLight", "Thin", "Medium", "DemiBold", "Bold", "ExtraBold", "Black"]
|
||||
scope: "Font"
|
||||
enabled: !styleNameComboBox.styleSet
|
||||
}
|
||||
|
||||
ExpandingSpacer {}
|
||||
}
|
||||
|
||||
PropertyLabel {
|
||||
text: qsTr("Style name")
|
||||
tooltip: qsTr("Font's style.")
|
||||
@@ -267,7 +248,30 @@ Section {
|
||||
supportGradient: false
|
||||
}
|
||||
|
||||
PropertyLabel { text: qsTr("Emphasis") }
|
||||
PropertyLabel {
|
||||
text: qsTr("Weight")
|
||||
tooltip: qsTr("Font's weight.")
|
||||
enabled: !styleNameComboBox.styleSet
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
ComboBox {
|
||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||
+ StudioTheme.Values.actionIndicatorWidth
|
||||
width: implicitWidth
|
||||
backendValue: getBackendValue("weight")
|
||||
model: ["Normal", "Light", "ExtraLight", "Thin", "Medium", "DemiBold", "Bold", "ExtraBold", "Black"]
|
||||
scope: "Font"
|
||||
enabled: !styleNameComboBox.styleSet
|
||||
}
|
||||
|
||||
ExpandingSpacer {}
|
||||
}
|
||||
|
||||
PropertyLabel {
|
||||
text: qsTr("Emphasis")
|
||||
enabled: !styleNameComboBox.styleSet
|
||||
}
|
||||
|
||||
FontStyleButtons {
|
||||
bold: root.boldStyle
|
||||
|
@@ -35,6 +35,7 @@
|
||||
<style name="String" foreground="#636363"/>
|
||||
<style name="Text" foreground="#000000" background="#ffffff"/>
|
||||
<style name="Type"/>
|
||||
<style name="Namespace"/>
|
||||
<style name="VirtualMethod" italic="true"/>
|
||||
<style name="Occurrences.Unused" underlineColor="#8F8F8F" underlineStyle="SingleUnderline"/>
|
||||
<style name="Warning" underlineColor="#505050" underlineStyle="SingleUnderline"/>
|
||||
|
@@ -632,6 +632,10 @@ LibraryInfo Snapshot::libraryInfo(const QString &path) const
|
||||
return _libraries.value(QDir::cleanPath(path));
|
||||
}
|
||||
|
||||
LibraryInfo Snapshot::libraryInfo(const Utils::FilePath &path) const
|
||||
{
|
||||
return _libraries.value(path.cleanPath().toString());
|
||||
}
|
||||
|
||||
void ModuleApiInfo::addToHash(QCryptographicHash &hash) const
|
||||
{
|
||||
|
@@ -256,7 +256,8 @@ public:
|
||||
|
||||
Document::Ptr document(const QString &fileName) const;
|
||||
QList<Document::Ptr> documentsInDirectory(const QString &path) const;
|
||||
LibraryInfo libraryInfo(const QString &path) const;
|
||||
LibraryInfo libraryInfo(const QString &path) const; // FIXME: Remove
|
||||
LibraryInfo libraryInfo(const Utils::FilePath &path) const;
|
||||
|
||||
Document::MutablePtr documentFromSource(const QString &code,
|
||||
const QString &fileName,
|
||||
|
@@ -684,19 +684,19 @@ void ModelManagerInterface::updateDocument(const Document::Ptr &doc)
|
||||
emit documentUpdated(doc);
|
||||
}
|
||||
|
||||
void ModelManagerInterface::updateLibraryInfo(const QString &path, const LibraryInfo &info)
|
||||
void ModelManagerInterface::updateLibraryInfo(const FilePath &path, const LibraryInfo &info)
|
||||
{
|
||||
if (!info.pluginTypeInfoError().isEmpty())
|
||||
qCDebug(qmljsLog) << "Dumping errors for " << path << ":" << info.pluginTypeInfoError();
|
||||
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
m_validSnapshot.insertLibraryInfo(path, info);
|
||||
m_newestSnapshot.insertLibraryInfo(path, info);
|
||||
m_validSnapshot.insertLibraryInfo(path.toString(), info);
|
||||
m_newestSnapshot.insertLibraryInfo(path.toString(), info);
|
||||
}
|
||||
// only emit if we got new useful information
|
||||
if (info.isValid())
|
||||
emit libraryInfoUpdated(path, info);
|
||||
emit libraryInfoUpdated(path.toString(), info);
|
||||
}
|
||||
|
||||
static QStringList filesInDirectoryForLanguages(const QString &path,
|
||||
@@ -773,7 +773,7 @@ enum class LibraryStatus {
|
||||
Unknown
|
||||
};
|
||||
|
||||
static LibraryStatus libraryStatus(const QString &path, const Snapshot &snapshot,
|
||||
static LibraryStatus libraryStatus(const FilePath &path, const Snapshot &snapshot,
|
||||
QSet<QString> *newLibraries)
|
||||
{
|
||||
if (path.isEmpty())
|
||||
@@ -782,7 +782,7 @@ static LibraryStatus libraryStatus(const QString &path, const Snapshot &snapshot
|
||||
const LibraryInfo &existingInfo = snapshot.libraryInfo(path);
|
||||
if (existingInfo.isValid())
|
||||
return LibraryStatus::Accepted;
|
||||
if (newLibraries->contains(path))
|
||||
if (newLibraries->contains(path.toString()))
|
||||
return LibraryStatus::Accepted;
|
||||
// if we looked at the path before, done
|
||||
return existingInfo.wasScanned()
|
||||
@@ -790,7 +790,7 @@ static LibraryStatus libraryStatus(const QString &path, const Snapshot &snapshot
|
||||
: LibraryStatus::Unknown;
|
||||
}
|
||||
|
||||
static bool findNewQmlApplicationInPath(const QString &path,
|
||||
static bool findNewQmlApplicationInPath(const FilePath &path,
|
||||
const Snapshot &snapshot,
|
||||
ModelManagerInterface *modelManager,
|
||||
QSet<QString> *newLibraries)
|
||||
@@ -803,8 +803,8 @@ static bool findNewQmlApplicationInPath(const QString &path,
|
||||
|
||||
QString qmltypesFile;
|
||||
|
||||
QDir dir(path);
|
||||
QDirIterator it(path, QStringList { "*.qmltypes" }, QDir::Files);
|
||||
QDir dir(path.toString());
|
||||
QDirIterator it(path.toString(), QStringList { "*.qmltypes" }, QDir::Files);
|
||||
|
||||
if (!it.hasNext())
|
||||
return false;
|
||||
@@ -828,7 +828,7 @@ static bool findNewQmlLibraryInPath(const QString &path,
|
||||
QSet<QString> *newLibraries,
|
||||
bool ignoreMissing)
|
||||
{
|
||||
switch (libraryStatus(path, snapshot, newLibraries)) {
|
||||
switch (libraryStatus(FilePath::fromString(path), snapshot, newLibraries)) {
|
||||
case LibraryStatus::Accepted: return true;
|
||||
case LibraryStatus::Rejected: return false;
|
||||
default: break;
|
||||
@@ -839,7 +839,7 @@ static bool findNewQmlLibraryInPath(const QString &path,
|
||||
if (!qmldirFile.exists()) {
|
||||
if (!ignoreMissing) {
|
||||
LibraryInfo libraryInfo(LibraryInfo::NotFound);
|
||||
modelManager->updateLibraryInfo(path, libraryInfo);
|
||||
modelManager->updateLibraryInfo(FilePath::fromString(path), libraryInfo);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -858,7 +858,7 @@ static bool findNewQmlLibraryInPath(const QString &path,
|
||||
|
||||
const QString libraryPath = QFileInfo(qmldirFile).absolutePath();
|
||||
newLibraries->insert(libraryPath);
|
||||
modelManager->updateLibraryInfo(libraryPath, LibraryInfo(qmldirParser));
|
||||
modelManager->updateLibraryInfo(FilePath::fromString(libraryPath), LibraryInfo(qmldirParser));
|
||||
modelManager->loadPluginTypes(QFileInfo(libraryPath).canonicalFilePath(), libraryPath,
|
||||
QString(), QString());
|
||||
|
||||
@@ -1252,7 +1252,7 @@ void ModelManagerInterface::updateImportPaths()
|
||||
for (const Document::Ptr &doc : qAsConst(snapshot))
|
||||
findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries);
|
||||
for (const QString &path : qAsConst(allApplicationDirectories))
|
||||
findNewQmlApplicationInPath(path, snapshot, this, &newLibraries);
|
||||
findNewQmlApplicationInPath(FilePath::fromString(path), snapshot, this, &newLibraries);
|
||||
|
||||
updateSourceFiles(importedFiles, true);
|
||||
|
||||
@@ -1433,7 +1433,7 @@ LibraryInfo ModelManagerInterface::builtins(const Document::Ptr &doc) const
|
||||
{
|
||||
const ProjectInfo info = projectInfoForPath(doc->fileName());
|
||||
if (!info.qtQmlPath.isEmpty())
|
||||
return m_validSnapshot.libraryInfo(info.qtQmlPath.toString());
|
||||
return m_validSnapshot.libraryInfo(info.qtQmlPath);
|
||||
return LibraryInfo();
|
||||
}
|
||||
|
||||
|
@@ -156,7 +156,7 @@ public:
|
||||
void updateProjectInfo(const ProjectInfo &pinfo, ProjectExplorer::Project *p);
|
||||
|
||||
void updateDocument(const QmlJS::Document::Ptr& doc);
|
||||
void updateLibraryInfo(const QString &path, const QmlJS::LibraryInfo &info);
|
||||
void updateLibraryInfo(const Utils::FilePath &path, const QmlJS::LibraryInfo &info);
|
||||
void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc);
|
||||
void updateQrcFile(const QString &path);
|
||||
ProjectInfo projectInfoForPath(const QString &path) const;
|
||||
|
@@ -89,25 +89,23 @@ void PluginDumper::onLoadBuiltinTypes(const QmlJS::ModelManagerInterface::Projec
|
||||
if (info.qmlDumpPath.isEmpty() || info.qtQmlPath.isEmpty())
|
||||
return;
|
||||
|
||||
// FIXME: This doesn't work for non-local paths.
|
||||
const QString importsPath = QDir::cleanPath(info.qtQmlPath.toString());
|
||||
if (m_runningQmldumps.values().contains(importsPath))
|
||||
if (m_runningQmldumps.values().contains(info.qmlDumpPath))
|
||||
return;
|
||||
|
||||
LibraryInfo builtinInfo;
|
||||
if (!force) {
|
||||
const Snapshot snapshot = m_modelManager->snapshot();
|
||||
builtinInfo = snapshot.libraryInfo(info.qtQmlPath.toString());
|
||||
builtinInfo = snapshot.libraryInfo(info.qtQmlPath);
|
||||
if (builtinInfo.isValid())
|
||||
return;
|
||||
}
|
||||
builtinInfo = LibraryInfo(LibraryInfo::Found);
|
||||
m_modelManager->updateLibraryInfo(info.qtQmlPath.toString(), builtinInfo);
|
||||
m_modelManager->updateLibraryInfo(info.qtQmlPath, builtinInfo);
|
||||
|
||||
// prefer QTDIR/qml/builtins.qmltypes if available
|
||||
const QString builtinQmltypesPath = info.qtQmlPath.toString() + QLatin1String("/builtins.qmltypes");
|
||||
if (QFile::exists(builtinQmltypesPath)) {
|
||||
loadQmltypesFile(QStringList(builtinQmltypesPath), info.qtQmlPath.toString(), builtinInfo);
|
||||
const FilePath builtinQmltypesPath = info.qtQmlPath / "builtins.qmltypes";
|
||||
if (builtinQmltypesPath.exists()) {
|
||||
loadQmltypesFile({builtinQmltypesPath}, info.qtQmlPath, builtinInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,16 +113,9 @@ void PluginDumper::onLoadBuiltinTypes(const QmlJS::ModelManagerInterface::Projec
|
||||
m_qtToInfo.insert(info.qtQmlPath.toString(), info);
|
||||
}
|
||||
|
||||
static QString makeAbsolute(const QString &path, const QString &base)
|
||||
{
|
||||
if (QFileInfo(path).isAbsolute())
|
||||
return path;
|
||||
return QString::fromLatin1("%1/%3").arg(base, path);
|
||||
}
|
||||
|
||||
void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &importPath, const QString &importUri, const QString &importVersion)
|
||||
{
|
||||
const QString canonicalLibraryPath = QDir::cleanPath(libraryPath);
|
||||
const FilePath canonicalLibraryPath = FilePath::fromUserInput(libraryPath).cleanPath();
|
||||
if (m_runningQmldumps.values().contains(canonicalLibraryPath))
|
||||
return;
|
||||
const Snapshot snapshot = m_modelManager->snapshot();
|
||||
@@ -135,7 +126,7 @@ void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &
|
||||
// avoid inserting the same plugin twice
|
||||
int index;
|
||||
for (index = 0; index < m_plugins.size(); ++index) {
|
||||
if (m_plugins.at(index).qmldirPath == libraryPath)
|
||||
if (m_plugins.at(index).qmldirPath == canonicalLibraryPath)
|
||||
break;
|
||||
}
|
||||
if (index == m_plugins.size())
|
||||
@@ -148,10 +139,10 @@ void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &
|
||||
plugin.importVersion = importVersion;
|
||||
|
||||
// add default qmltypes file if it exists
|
||||
QDirIterator it(canonicalLibraryPath, QStringList { "*.qmltypes" }, QDir::Files);
|
||||
QDirIterator it(canonicalLibraryPath.toString(), QStringList { "*.qmltypes" }, QDir::Files);
|
||||
|
||||
while (it.hasNext()) {
|
||||
const QString defaultQmltypesPath = makeAbsolute(it.next(), canonicalLibraryPath);
|
||||
const FilePath defaultQmltypesPath = canonicalLibraryPath.resolvePath(it.next());
|
||||
|
||||
if (!plugin.typeInfoPaths.contains(defaultQmltypesPath))
|
||||
plugin.typeInfoPaths += defaultQmltypesPath;
|
||||
@@ -159,29 +150,29 @@ void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &
|
||||
|
||||
// add typeinfo files listed in qmldir
|
||||
foreach (const QString &typeInfo, libraryInfo.typeInfos()) {
|
||||
QString pathNow = makeAbsolute(typeInfo, canonicalLibraryPath);
|
||||
if (!plugin.typeInfoPaths.contains(pathNow) && QFile::exists(pathNow))
|
||||
const FilePath pathNow = canonicalLibraryPath.resolvePath(typeInfo);
|
||||
if (!plugin.typeInfoPaths.contains(pathNow) && pathNow.exists())
|
||||
plugin.typeInfoPaths += pathNow;
|
||||
}
|
||||
|
||||
// watch plugin libraries
|
||||
foreach (const QmlDirParser::Plugin &plugin, snapshot.libraryInfo(canonicalLibraryPath).plugins()) {
|
||||
const QString pluginLibrary = resolvePlugin(canonicalLibraryPath, plugin.path, plugin.name);
|
||||
const QString pluginLibrary = resolvePlugin(canonicalLibraryPath.toString(), plugin.path, plugin.name);
|
||||
if (!pluginLibrary.isEmpty()) {
|
||||
if (!pluginWatcher()->watchesFile(pluginLibrary))
|
||||
pluginWatcher()->addFile(pluginLibrary, Utils::FileSystemWatcher::WatchModifiedDate);
|
||||
pluginWatcher()->addFile(pluginLibrary, FileSystemWatcher::WatchModifiedDate);
|
||||
m_libraryToPluginIndex.insert(pluginLibrary, index);
|
||||
}
|
||||
}
|
||||
|
||||
// watch library qmltypes file
|
||||
if (!plugin.typeInfoPaths.isEmpty()) {
|
||||
foreach (const QString &path, plugin.typeInfoPaths) {
|
||||
if (!QFile::exists(path))
|
||||
for (const FilePath &path : qAsConst(plugin.typeInfoPaths)) {
|
||||
if (!path.exists())
|
||||
continue;
|
||||
if (!pluginWatcher()->watchesFile(path))
|
||||
pluginWatcher()->addFile(path, Utils::FileSystemWatcher::WatchModifiedDate);
|
||||
m_libraryToPluginIndex.insert(path, index);
|
||||
if (!pluginWatcher()->watchesFile(path.toString()))
|
||||
pluginWatcher()->addFile(path.toString(), FileSystemWatcher::WatchModifiedDate);
|
||||
m_libraryToPluginIndex.insert(path.toString(), index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,26 +186,25 @@ void PluginDumper::dumpAllPlugins()
|
||||
}
|
||||
}
|
||||
|
||||
static QString noTypeinfoError(const QString &libraryPath)
|
||||
static QString noTypeinfoError(const FilePath &libraryPath)
|
||||
{
|
||||
return PluginDumper::tr("QML module does not contain information about components contained in plugins.\n\n"
|
||||
"Module path: %1\n"
|
||||
"See \"Using QML Modules with Plugins\" in the documentation.").arg(
|
||||
libraryPath);
|
||||
libraryPath.toUserOutput());
|
||||
}
|
||||
|
||||
static QString qmldumpErrorMessage(const QString &libraryPath, const QString &error)
|
||||
static QString qmldumpErrorMessage(const FilePath &libraryPath, const QString &error)
|
||||
{
|
||||
return noTypeinfoError(libraryPath) + QLatin1String("\n\n") +
|
||||
return noTypeinfoError(libraryPath) + "\n\n" +
|
||||
PluginDumper::tr("Automatic type dump of QML module failed.\nErrors:\n%1").
|
||||
arg(error) + QLatin1Char('\n');
|
||||
}
|
||||
|
||||
static QString qmldumpFailedMessage(const QString &libraryPath, const QString &error)
|
||||
static QString qmldumpFailedMessage(const FilePath &libraryPath, const QString &error)
|
||||
{
|
||||
QString firstLines =
|
||||
QStringList(error.split(QLatin1Char('\n')).mid(0, 10)).join(QLatin1Char('\n'));
|
||||
return noTypeinfoError(libraryPath) + QLatin1String("\n\n") +
|
||||
QString firstLines = QStringList(error.split('\n').mid(0, 10)).join('\n');
|
||||
return noTypeinfoError(libraryPath) + "\n\n" +
|
||||
PluginDumper::tr("Automatic type dump of QML module failed.\n"
|
||||
"First 10 lines or errors:\n"
|
||||
"\n"
|
||||
@@ -224,11 +214,11 @@ static QString qmldumpFailedMessage(const QString &libraryPath, const QString &e
|
||||
).arg(firstLines);
|
||||
}
|
||||
|
||||
static void printParseWarnings(const QString &libraryPath, const QString &warning)
|
||||
static void printParseWarnings(const FilePath &libraryPath, const QString &warning)
|
||||
{
|
||||
ModelManagerInterface::writeWarning(
|
||||
PluginDumper::tr("Warnings while parsing QML type information of %1:\n"
|
||||
"%2").arg(libraryPath, warning));
|
||||
"%2").arg(libraryPath.toUserOutput(), warning));
|
||||
}
|
||||
|
||||
static QString qmlPluginDumpErrorMessage(QtcProcess *process)
|
||||
@@ -269,7 +259,7 @@ void PluginDumper::qmlPluginTypeDumpDone(QtcProcess *process)
|
||||
{
|
||||
process->deleteLater();
|
||||
|
||||
const QString libraryPath = m_runningQmldumps.take(process);
|
||||
const FilePath libraryPath = m_runningQmldumps.take(process);
|
||||
if (libraryPath.isEmpty())
|
||||
return;
|
||||
const Snapshot snapshot = m_modelManager->snapshot();
|
||||
@@ -298,7 +288,7 @@ void PluginDumper::qmlPluginTypeDumpDone(QtcProcess *process)
|
||||
CppQmlTypesInfo infos;
|
||||
CppQmlTypesLoader::parseQmlTypeDescriptions(output, &infos.objectsList, &infos.moduleApis, &infos.dependencies,
|
||||
&infos.error, &infos.warning,
|
||||
QLatin1String("<dump of ") + libraryPath + QLatin1Char('>'));
|
||||
"<dump of " + libraryPath.toUserOutput() + '>');
|
||||
future.reportFinished(&infos);
|
||||
});
|
||||
m_modelManager->addFuture(future);
|
||||
@@ -338,13 +328,13 @@ void PluginDumper::qmlPluginTypeDumpError(QtcProcess *process)
|
||||
{
|
||||
process->deleteLater();
|
||||
|
||||
const QString libraryPath = m_runningQmldumps.take(process);
|
||||
const FilePath libraryPath = m_runningQmldumps.take(process);
|
||||
if (libraryPath.isEmpty())
|
||||
return;
|
||||
const QString errorMessages = qmlPluginDumpErrorMessage(process);
|
||||
const Snapshot snapshot = m_modelManager->snapshot();
|
||||
LibraryInfo libraryInfo = snapshot.libraryInfo(libraryPath);
|
||||
if (!libraryPath.endsWith(QLatin1String("private"), Qt::CaseInsensitive))
|
||||
if (!libraryPath.path().endsWith(QLatin1String("private"), Qt::CaseInsensitive))
|
||||
ModelManagerInterface::writeWarning(qmldumpErrorMessage(libraryPath, errorMessages));
|
||||
libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, qmldumpFailedMessage(libraryPath, errorMessages));
|
||||
libraryInfo.updateFingerprint();
|
||||
@@ -361,14 +351,15 @@ void PluginDumper::pluginChanged(const QString &pluginLibrary)
|
||||
dump(plugin);
|
||||
}
|
||||
|
||||
QFuture<PluginDumper::QmlTypeDescription> PluginDumper::loadQmlTypeDescription(const QStringList &paths) const {
|
||||
QFuture<PluginDumper::QmlTypeDescription> PluginDumper::loadQmlTypeDescription(const FilePaths &paths) const
|
||||
{
|
||||
auto future = Utils::runAsync([=](QFutureInterface<PluginDumper::QmlTypeDescription> &future)
|
||||
{
|
||||
PluginDumper::QmlTypeDescription result;
|
||||
|
||||
for (const QString &p: paths) {
|
||||
for (const FilePath &p: paths) {
|
||||
Utils::FileReader reader;
|
||||
if (!reader.fetch(Utils::FilePath::fromString(p), QFile::Text)) {
|
||||
if (!reader.fetch(p, QFile::Text)) {
|
||||
result.errors += reader.errorString();
|
||||
continue;
|
||||
}
|
||||
@@ -378,9 +369,9 @@ QFuture<PluginDumper::QmlTypeDescription> PluginDumper::loadQmlTypeDescription(c
|
||||
QList<ModuleApiInfo> apis;
|
||||
QStringList deps;
|
||||
CppQmlTypesLoader::parseQmlTypeDescriptions(reader.data(), &objs, &apis, &deps,
|
||||
&error, &warning, p);
|
||||
&error, &warning, p.toString());
|
||||
if (!error.isEmpty()) {
|
||||
result.errors += tr("Failed to parse \"%1\".\nError: %2").arg(p, error);
|
||||
result.errors += tr("Failed to parse \"%1\".\nError: %2").arg(p.toUserOutput(), error);
|
||||
} else {
|
||||
result.objects += objs.values();
|
||||
result.moduleApis += apis;
|
||||
@@ -444,27 +435,26 @@ QString PluginDumper::buildQmltypesPath(const QString &name) const
|
||||
* Recursively load type descriptions of dependencies, collecting results
|
||||
* in \a objects.
|
||||
*/
|
||||
QFuture<PluginDumper::DependencyInfo> PluginDumper::loadDependencies(const QStringList &dependencies,
|
||||
QSharedPointer<QSet<QString>> visited) const
|
||||
QFuture<PluginDumper::DependencyInfo> PluginDumper::loadDependencies(const FilePaths &dependencies,
|
||||
QSharedPointer<QSet<FilePath>> visited) const
|
||||
{
|
||||
auto iface = QSharedPointer<QFutureInterface<PluginDumper::DependencyInfo>>(new QFutureInterface<PluginDumper::DependencyInfo>);
|
||||
|
||||
if (visited.isNull()) {
|
||||
visited = QSharedPointer<QSet<QString>>(new QSet<QString>());
|
||||
}
|
||||
if (visited.isNull())
|
||||
visited = QSharedPointer<QSet<FilePath>>(new QSet<FilePath>());
|
||||
|
||||
QStringList dependenciesPaths;
|
||||
FilePaths dependenciesPaths;
|
||||
QString path;
|
||||
for (const QString &name: dependencies) {
|
||||
path = buildQmltypesPath(name);
|
||||
for (const FilePath &name : dependencies) {
|
||||
path = buildQmltypesPath(name.toString());
|
||||
if (!path.isNull())
|
||||
dependenciesPaths << path;
|
||||
dependenciesPaths << FilePath::fromString(path);
|
||||
visited->insert(name);
|
||||
}
|
||||
|
||||
Utils::onFinished(loadQmlTypeDescription(dependenciesPaths), const_cast<PluginDumper*>(this), [=] (const QFuture<PluginDumper::QmlTypeDescription> &typesFuture) {
|
||||
PluginDumper::QmlTypeDescription typesResult = typesFuture.result();
|
||||
QStringList newDependencies = typesResult.dependencies;
|
||||
FilePaths newDependencies = Utils::transform(typesResult.dependencies, &FilePath::fromString);
|
||||
newDependencies = Utils::toList(Utils::toSet(newDependencies) - *visited.data());
|
||||
if (!newDependencies.isEmpty()) {
|
||||
Utils::onFinished(loadDependencies(newDependencies, visited),
|
||||
@@ -564,7 +554,7 @@ static void applyQt515MissingImportWorkaround(const QString &path, LibraryInfo &
|
||||
}
|
||||
|
||||
void PluginDumper::prepareLibraryInfo(LibraryInfo &libInfo,
|
||||
const QString &libraryPath,
|
||||
const FilePath &libraryPath,
|
||||
const QStringList &deps,
|
||||
const QStringList &errors,
|
||||
const QStringList &warnings,
|
||||
@@ -588,13 +578,13 @@ void PluginDumper::prepareLibraryInfo(LibraryInfo &libInfo,
|
||||
if (!warnings.isEmpty())
|
||||
printParseWarnings(libraryPath, warnings.join(QLatin1String("\n")));
|
||||
|
||||
applyQt515MissingImportWorkaround(libraryPath, libInfo);
|
||||
applyQt515MissingImportWorkaround(libraryPath.toString(), libInfo);
|
||||
|
||||
libInfo.updateFingerprint();
|
||||
}
|
||||
|
||||
void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
|
||||
const QString &libraryPath,
|
||||
void PluginDumper::loadQmltypesFile(const FilePaths &qmltypesFilePaths,
|
||||
const FilePath &libraryPath,
|
||||
QmlJS::LibraryInfo libraryInfo)
|
||||
{
|
||||
Utils::onFinished(loadQmlTypeDescription(qmltypesFilePaths), this, [=](const QFuture<PluginDumper::QmlTypeDescription> &typesFuture)
|
||||
@@ -602,7 +592,8 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths,
|
||||
PluginDumper::QmlTypeDescription typesResult = typesFuture.result();
|
||||
if (!typesResult.dependencies.isEmpty())
|
||||
{
|
||||
Utils::onFinished(loadDependencies(typesResult.dependencies, QSharedPointer<QSet<QString>>()), this,
|
||||
Utils::onFinished(loadDependencies(Utils::transform(typesResult.dependencies, &FilePath::fromString),
|
||||
QSharedPointer<QSet<FilePath>>()), this,
|
||||
[typesResult, libraryInfo, libraryPath, this] (const QFuture<PluginDumper::DependencyInfo> &loadFuture)
|
||||
{
|
||||
PluginDumper::DependencyInfo loadResult = loadFuture.result();
|
||||
@@ -640,7 +631,7 @@ void PluginDumper::runQmlDump(const ModelManagerInterface::ProjectInfo &info,
|
||||
connect(process, &QtcProcess::finished, this, [this, process] { qmlPluginTypeDumpDone(process); });
|
||||
connect(process, &QtcProcess::errorOccurred, this, [this, process] { qmlPluginTypeDumpError(process); });
|
||||
process->start();
|
||||
m_runningQmldumps.insert(process, importPath.toString());
|
||||
m_runningQmldumps.insert(process, importPath);
|
||||
}
|
||||
|
||||
void PluginDumper::dump(const Plugin &plugin)
|
||||
@@ -686,7 +677,7 @@ void PluginDumper::dump(const Plugin &plugin)
|
||||
args << plugin.importUri;
|
||||
args << plugin.importVersion;
|
||||
args << (plugin.importPath.isEmpty() ? QLatin1String(".") : plugin.importPath);
|
||||
runQmlDump(info, args, FilePath::fromString(plugin.qmldirPath));
|
||||
runQmlDump(info, args, plugin.qmldirPath);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@@ -65,11 +65,11 @@ private:
|
||||
private:
|
||||
class Plugin {
|
||||
public:
|
||||
QString qmldirPath;
|
||||
Utils::FilePath qmldirPath;
|
||||
QString importPath;
|
||||
QString importUri;
|
||||
QString importVersion;
|
||||
QStringList typeInfoPaths;
|
||||
Utils::FilePaths typeInfoPaths;
|
||||
};
|
||||
|
||||
class QmlTypeDescription {
|
||||
@@ -91,14 +91,14 @@ private:
|
||||
void runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info, const QStringList &arguments,
|
||||
const Utils::FilePath &importPath);
|
||||
void dump(const Plugin &plugin);
|
||||
QFuture<QmlTypeDescription> loadQmlTypeDescription(const QStringList &path) const;
|
||||
QFuture<QmlTypeDescription> loadQmlTypeDescription(const Utils::FilePaths &path) const;
|
||||
QString buildQmltypesPath(const QString &name) const;
|
||||
|
||||
QFuture<PluginDumper::DependencyInfo> loadDependencies(const QStringList &dependencies,
|
||||
QSharedPointer<QSet<QString>> visited) const;
|
||||
QFuture<PluginDumper::DependencyInfo> loadDependencies(const Utils::FilePaths &dependencies,
|
||||
QSharedPointer<QSet<Utils::FilePath> > visited) const;
|
||||
|
||||
void loadQmltypesFile(const QStringList &qmltypesFilePaths,
|
||||
const QString &libraryPath,
|
||||
void loadQmltypesFile(const Utils::FilePaths &qmltypesFilePaths,
|
||||
const Utils::FilePath &libraryPath,
|
||||
QmlJS::LibraryInfo libraryInfo);
|
||||
QString resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath,
|
||||
const QString &baseName);
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
private:
|
||||
Utils::FileSystemWatcher *pluginWatcher();
|
||||
void prepareLibraryInfo(LibraryInfo &libInfo,
|
||||
const QString &libraryPath,
|
||||
const Utils::FilePath &libraryPath,
|
||||
const QStringList &deps,
|
||||
const QStringList &errors,
|
||||
const QStringList &warnings,
|
||||
@@ -118,7 +118,7 @@ private:
|
||||
|
||||
ModelManagerInterface *m_modelManager;
|
||||
Utils::FileSystemWatcher *m_pluginWatcher;
|
||||
QHash<Utils::QtcProcess *, QString> m_runningQmldumps;
|
||||
QHash<Utils::QtcProcess *, Utils::FilePath> m_runningQmldumps;
|
||||
QList<Plugin> m_plugins;
|
||||
QHash<QString, int> m_libraryToPluginIndex;
|
||||
QHash<QString, QmlJS::ModelManagerInterface::ProjectInfo> m_qtToInfo;
|
||||
|
@@ -440,7 +440,7 @@ FilePath FilePath::fromFileInfo(const QFileInfo &info)
|
||||
QFileInfo FilePath::toFileInfo() const
|
||||
{
|
||||
QTC_ASSERT(!needsDevice(), return QFileInfo());
|
||||
return QFileInfo(m_data);
|
||||
return QFileInfo(cleanPath().path());
|
||||
}
|
||||
|
||||
FilePath FilePath::fromUrl(const QUrl &url)
|
||||
|
@@ -125,7 +125,9 @@ bool MultiTextCursor::hasSelection() const
|
||||
QString MultiTextCursor::selectedText() const
|
||||
{
|
||||
QString text;
|
||||
for (const QTextCursor &cursor : m_cursors) {
|
||||
QList<QTextCursor> cursors = m_cursors;
|
||||
Utils::sort(cursors);
|
||||
for (const QTextCursor &cursor : cursors) {
|
||||
const QString &cursorText = cursor.selectedText();
|
||||
if (cursorText.isEmpty())
|
||||
continue;
|
||||
@@ -169,7 +171,9 @@ void MultiTextCursor::insertText(const QString &text, bool selectNewText)
|
||||
lines.pop_back();
|
||||
int index = 0;
|
||||
if (lines.count() == m_cursors.count()) {
|
||||
for (QTextCursor &cursor : m_cursors)
|
||||
QList<QTextCursor> cursors = m_cursors;
|
||||
Utils::sort(cursors);
|
||||
for (QTextCursor &cursor : cursors)
|
||||
insertAndSelect(cursor, lines.at(index++), selectNewText);
|
||||
m_cursors.last().endEditBlock();
|
||||
return;
|
||||
|
@@ -90,7 +90,8 @@ AndroidDeviceWidget::AndroidDeviceWidget(const IDevice::Ptr &device)
|
||||
formLayout->addRow(AndroidDevice::tr("Device type:"), new QLabel(dev->deviceTypeName()));
|
||||
|
||||
const QString serialNumber = dev->serialNumber();
|
||||
const QString printableSerialNumber = serialNumber.isEmpty() ? tr("Unknown") : serialNumber;
|
||||
const QString printableSerialNumber = serialNumber.isEmpty() ? AndroidDevice::tr("Unknown")
|
||||
: serialNumber;
|
||||
formLayout->addRow(AndroidDevice::tr("Serial number:"), new QLabel(printableSerialNumber));
|
||||
|
||||
const QString abis = dev->supportedAbis().join(", ");
|
||||
@@ -100,8 +101,9 @@ AndroidDeviceWidget::AndroidDeviceWidget(const IDevice::Ptr &device)
|
||||
formLayout->addRow(AndroidDevice::tr("OS version:"), new QLabel(osString));
|
||||
|
||||
if (dev->machineType() == IDevice::Hardware) {
|
||||
const QString authorizedStr = dev->deviceState() == IDevice::DeviceReadyToUse ? tr("Yes")
|
||||
: tr("No");
|
||||
const QString authorizedStr = dev->deviceState() == IDevice::DeviceReadyToUse
|
||||
? AndroidDevice::tr("Yes")
|
||||
: AndroidDevice::tr("No");
|
||||
formLayout->addRow(AndroidDevice::tr("Authorized:"), new QLabel(authorizedStr));
|
||||
}
|
||||
|
||||
@@ -117,7 +119,7 @@ AndroidDeviceWidget::AndroidDeviceWidget(const IDevice::Ptr &device)
|
||||
|
||||
QString AndroidDeviceWidget::dialogTitle()
|
||||
{
|
||||
return tr("Android Device Manager");
|
||||
return AndroidDevice::tr("Android Device Manager");
|
||||
}
|
||||
|
||||
bool AndroidDeviceWidget::criticalDialog(const QString &error, QWidget *parent)
|
||||
@@ -480,7 +482,8 @@ void AndroidDeviceManager::eraseAvd(const IDevice::Ptr &device, QWidget *parent)
|
||||
return;
|
||||
|
||||
const QString name = static_cast<const AndroidDevice *>(device.data())->avdName();
|
||||
const QString question = tr("Erase the Android AVD \"%1\"?\nThis cannot be undone.").arg(name);
|
||||
const QString question
|
||||
= AndroidDevice::tr("Erase the Android AVD \"%1\"?\nThis cannot be undone.").arg(name);
|
||||
if (!AndroidDeviceWidget::questionDialog(question, parent))
|
||||
return;
|
||||
|
||||
@@ -515,9 +518,10 @@ void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
|
||||
"https://developer.android.com/studio/run/emulator-commandline#startup-options";
|
||||
|
||||
QInputDialog dialog(parent ? parent : Core::ICore::dialogParent());
|
||||
dialog.setWindowTitle(tr("Emulator Command-line Startup Options"));
|
||||
dialog.setLabelText(tr("Emulator command-line startup options "
|
||||
"(<a href=\"%1\">Help Web Page</a>):").arg(helpUrl));
|
||||
dialog.setWindowTitle(AndroidDevice::tr("Emulator Command-line Startup Options"));
|
||||
dialog.setLabelText(AndroidDevice::tr("Emulator command-line startup options "
|
||||
"(<a href=\"%1\">Help Web Page</a>):")
|
||||
.arg(helpUrl));
|
||||
dialog.setTextValue(m_androidConfig.emulatorArgs().join(' '));
|
||||
|
||||
if (auto label = dialog.findChild<QLabel*>()) {
|
||||
|
@@ -327,7 +327,7 @@ AndroidRunnerWorker::~AndroidRunnerWorker()
|
||||
}
|
||||
|
||||
bool AndroidRunnerWorker::runAdb(const QStringList &args, QString *stdOut,
|
||||
const QByteArray &writeData)
|
||||
QString *stdErr, const QByteArray &writeData)
|
||||
{
|
||||
QStringList adbArgs = selector() + args;
|
||||
SdkToolResult result = AndroidManager::runAdbCommand(adbArgs, writeData);
|
||||
@@ -335,6 +335,8 @@ bool AndroidRunnerWorker::runAdb(const QStringList &args, QString *stdOut,
|
||||
emit remoteErrorOutput(result.stdErr());
|
||||
if (stdOut)
|
||||
*stdOut = result.stdOut();
|
||||
if (stdErr)
|
||||
*stdErr = result.stdErr();
|
||||
return result.success();
|
||||
}
|
||||
|
||||
@@ -651,10 +653,17 @@ void AndroidRunnerWorker::asyncStartHelper()
|
||||
.toUtf8().toBase64());
|
||||
}
|
||||
|
||||
if (!runAdb(args)) {
|
||||
QString stdErr;
|
||||
const bool startResult = runAdb(args, nullptr, &stdErr);
|
||||
if (!startResult) {
|
||||
emit remoteProcessFinished(tr("Failed to start the activity."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stdErr.isEmpty()) {
|
||||
emit remoteErrorOutput(tr("Activity Manager threw the error: %1").arg(stdErr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool AndroidRunnerWorker::startDebuggerServer(const QString &packageDir,
|
||||
|
@@ -47,7 +47,8 @@ public:
|
||||
AndroidRunnerWorker(ProjectExplorer::RunWorker *runner, const QString &packageName);
|
||||
~AndroidRunnerWorker() override;
|
||||
|
||||
bool runAdb(const QStringList &args, QString *stdOut = nullptr, const QByteArray &writeData = {});
|
||||
bool runAdb(const QStringList &args, QString *stdOut = nullptr, QString *stdErr = nullptr,
|
||||
const QByteArray &writeData = {});
|
||||
void adbKill(qint64 pid);
|
||||
QStringList selector() const;
|
||||
void forceStop();
|
||||
|
@@ -1302,15 +1302,25 @@ void ClangdClient::findUsages(TextDocument *document, const QTextCursor &cursor,
|
||||
const Utils::optional<QString> &replacement)
|
||||
{
|
||||
// Quick check: Are we even on anything searchable?
|
||||
if (d->searchTermFromCursor(cursor).isEmpty())
|
||||
const QString searchTerm = d->searchTermFromCursor(cursor);
|
||||
if (searchTerm.isEmpty())
|
||||
return;
|
||||
|
||||
// Get the proper spelling of the search term from clang, so we can put it into the
|
||||
const bool categorize = CppEditor::codeModelSettings()->categorizeFindReferences();
|
||||
|
||||
// If it's a "normal" symbol, go right ahead.
|
||||
if (searchTerm != "operator" && Utils::allOf(searchTerm, [](const QChar &c) {
|
||||
return c.isLetterOrNumber() || c == '_';
|
||||
})) {
|
||||
d->findUsages(document, cursor, searchTerm, replacement, categorize);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise get the proper spelling of the search term from clang, so we can put it into the
|
||||
// search widget.
|
||||
const TextDocumentIdentifier docId(DocumentUri::fromFilePath(document->filePath()));
|
||||
const TextDocumentPositionParams params(docId, Range(cursor).start());
|
||||
SymbolInfoRequest symReq(params);
|
||||
const bool categorize = CppEditor::codeModelSettings()->categorizeFindReferences();
|
||||
symReq.setResponseCallback([this, doc = QPointer(document), cursor, replacement, categorize]
|
||||
(const SymbolInfoRequest::Response &response) {
|
||||
if (!doc)
|
||||
@@ -2442,7 +2452,7 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
} else if (token.type == "comment") { // "comment" means code disabled via the preprocessor
|
||||
styles.mainStyle = C_DISABLED_CODE;
|
||||
} else if (token.type == "namespace") {
|
||||
styles.mainStyle = C_TYPE;
|
||||
styles.mainStyle = C_NAMESPACE;
|
||||
} else if (token.type == "property") {
|
||||
styles.mainStyle = C_FIELD;
|
||||
} else if (token.type == "enum") {
|
||||
@@ -2463,6 +2473,8 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
}
|
||||
if (token.modifiers.contains("declaration"))
|
||||
styles.mixinStyles.push_back(C_DECLARATION);
|
||||
if (token.modifiers.contains("static"))
|
||||
styles.mixinStyles.push_back(C_STATIC_MEMBER);
|
||||
if (isOutputParameter(token))
|
||||
styles.mixinStyles.push_back(C_OUTPUT_ARGUMENT);
|
||||
qCDebug(clangdLogHighlight) << "adding highlighting result"
|
||||
|
@@ -764,12 +764,12 @@ void ClangdTestHighlighting::test_data()
|
||||
QTest::newRow("struct declaration") << 50 << 8 << 50 << 11
|
||||
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
|
||||
QTest::newRow("namespace declaration") << 160 << 11 << 160 << 20
|
||||
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
|
||||
<< QList<int>{C_NAMESPACE, C_DECLARATION} << 0;
|
||||
QTest::newRow("namespace alias declaration") << 164 << 11 << 164 << 25
|
||||
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
|
||||
<< QList<int>{C_NAMESPACE, C_DECLARATION} << 0;
|
||||
QTest::newRow("struct in namespaced using declaration") << 165 << 18 << 165 << 35
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
QTest::newRow("namespace reference") << 166 << 1 << 166 << 10 << QList<int>{C_TYPE} << 0;
|
||||
QTest::newRow("namespace reference") << 166 << 1 << 166 << 10 << QList<int>{C_NAMESPACE} << 0;
|
||||
QTest::newRow("namespaced struct in global variable declaration") << 166 << 12 << 166 << 29
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
QTest::newRow("virtual function declaration") << 170 << 18 << 170 << 33
|
||||
@@ -992,7 +992,8 @@ void ClangdTestHighlighting::test_data()
|
||||
<< QList<int>{C_PUNCTUATION} << int(CppEditor::SemanticHighlighter::AngleBracketOpen);
|
||||
QTest::newRow("class template instantiation (closing angle bracket)") << 384 << 22 << 384 << 23
|
||||
<< QList<int>{C_PUNCTUATION} << int(CppEditor::SemanticHighlighter::AngleBracketClose);
|
||||
QTest::newRow("namespace in declaration") << 413 << 4 << 413 << 26 << QList<int>{C_TYPE} << 0;
|
||||
QTest::newRow("namespace in declaration") << 413 << 4 << 413 << 26
|
||||
<< QList<int>{C_NAMESPACE} << 0;
|
||||
QTest::newRow("namespaced class in declaration") << 413 << 28 << 413 << 41
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
QTest::newRow("class as template argument in declaration") << 413 << 42 << 413 << 52
|
||||
@@ -1099,9 +1100,9 @@ void ClangdTestHighlighting::test_data()
|
||||
QTest::newRow("local variable captured by lambda") << 442 << 24 << 442 << 27
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("static protected member") << 693 << 16 << 693 << 30
|
||||
<< QList<int>{C_FIELD, C_DECLARATION} << 0;
|
||||
<< QList<int>{C_FIELD, C_DECLARATION, C_STATIC_MEMBER} << 0;
|
||||
QTest::newRow("static private member") << 696 << 16 << 696 << 28
|
||||
<< QList<int>{C_FIELD, C_DECLARATION} << 0;
|
||||
<< QList<int>{C_FIELD, C_DECLARATION, C_STATIC_MEMBER} << 0;
|
||||
QTest::newRow("alias template declaration (opening angle bracket)") << 700 << 10 << 700 << 11
|
||||
<< QList<int>{C_PUNCTUATION} << int(CppEditor::SemanticHighlighter::AngleBracketOpen);
|
||||
QTest::newRow("alias template declaration (closing angle bracket)") << 700 << 16 << 700 << 17
|
||||
@@ -1163,14 +1164,14 @@ void ClangdTestHighlighting::test_data()
|
||||
QTest::newRow("reference to global variable") << 764 << 5 << 764 << 14
|
||||
<< QList<int>{C_GLOBAL} << 0;
|
||||
QTest::newRow("nested template instantiation (namespace 1)") << 773 << 8 << 773 << 11
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
<< QList<int>{C_NAMESPACE} << 0;
|
||||
QTest::newRow("nested template instantiation (type 1)") << 773 << 13 << 773 << 19
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
QTest::newRow("nested template instantiation (opening angle bracket 1)")
|
||||
<< 773 << 19 << 773 << 20
|
||||
<< QList<int>{C_PUNCTUATION} << int(CppEditor::SemanticHighlighter::AngleBracketOpen);
|
||||
QTest::newRow("nested template instantiation (namespace 2)") << 773 << 20 << 773 << 23
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
<< QList<int>{C_NAMESPACE} << 0;
|
||||
QTest::newRow("nested template instantiation (type 2)") << 773 << 25 << 773 << 29
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
QTest::newRow("nested template instantiation (opening angle bracket 2)")
|
||||
|
@@ -575,11 +575,11 @@ void ExternalToolConfig::updateItem(const QModelIndex &index)
|
||||
if (!tool)
|
||||
return;
|
||||
tool->setDescription(m_ui.description->text());
|
||||
QStringList executables = tool->executables();
|
||||
FilePaths executables = tool->executables();
|
||||
if (executables.size() > 0)
|
||||
executables[0] = m_ui.executable->rawPath();
|
||||
executables[0] = m_ui.executable->rawFilePath();
|
||||
else
|
||||
executables << m_ui.executable->rawPath();
|
||||
executables << m_ui.executable->rawFilePath();
|
||||
tool->setExecutables(executables);
|
||||
tool->setArguments(m_ui.arguments->text());
|
||||
tool->setWorkingDirectory(m_ui.workingDirectory->rawFilePath());
|
||||
@@ -607,8 +607,8 @@ void ExternalToolConfig::showInfoForItem(const QModelIndex &index)
|
||||
}
|
||||
m_ui.infoWidget->setEnabled(true);
|
||||
m_ui.description->setText(tool->description());
|
||||
m_ui.executable->setPath(tool->executables().isEmpty() ? QString()
|
||||
: tool->executables().constFirst());
|
||||
m_ui.executable->setFilePath(tool->executables().isEmpty() ? FilePath()
|
||||
: tool->executables().constFirst());
|
||||
m_ui.arguments->setText(tool->arguments());
|
||||
m_ui.workingDirectory->setFilePath(tool->workingDirectory());
|
||||
m_ui.outputBehavior->setCurrentIndex(int(tool->outputHandling()));
|
||||
|
@@ -154,7 +154,7 @@ int ExternalTool::order() const
|
||||
return m_order;
|
||||
}
|
||||
|
||||
QStringList ExternalTool::executables() const
|
||||
FilePaths ExternalTool::executables() const
|
||||
{
|
||||
return m_executables;
|
||||
}
|
||||
@@ -250,43 +250,36 @@ void ExternalTool::setDescription(const QString &description)
|
||||
m_description = description;
|
||||
}
|
||||
|
||||
|
||||
void ExternalTool::setOutputHandling(OutputHandling handling)
|
||||
{
|
||||
m_outputHandling = handling;
|
||||
}
|
||||
|
||||
|
||||
void ExternalTool::setErrorHandling(OutputHandling handling)
|
||||
{
|
||||
m_errorHandling = handling;
|
||||
}
|
||||
|
||||
|
||||
void ExternalTool::setModifiesCurrentDocument(bool modifies)
|
||||
{
|
||||
m_modifiesCurrentDocument = modifies;
|
||||
}
|
||||
|
||||
|
||||
void ExternalTool::setExecutables(const QStringList &executables)
|
||||
void ExternalTool::setExecutables(const FilePaths &executables)
|
||||
{
|
||||
m_executables = executables;
|
||||
}
|
||||
|
||||
|
||||
void ExternalTool::setArguments(const QString &arguments)
|
||||
{
|
||||
m_arguments = arguments;
|
||||
}
|
||||
|
||||
|
||||
void ExternalTool::setInput(const QString &input)
|
||||
{
|
||||
m_input = input;
|
||||
}
|
||||
|
||||
|
||||
void ExternalTool::setWorkingDirectory(const FilePath &workingDirectory)
|
||||
{
|
||||
m_workingDirectory = workingDirectory;
|
||||
@@ -417,7 +410,7 @@ ExternalTool * ExternalTool::createFromXml(const QByteArray &xml, QString *error
|
||||
}
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String(kPath)) {
|
||||
tool->m_executables.append(reader.readElementText());
|
||||
tool->m_executables.append(FilePath::fromString(reader.readElementText()));
|
||||
} else if (reader.name() == QLatin1String(kArguments)) {
|
||||
if (!tool->m_arguments.isEmpty()) {
|
||||
reader.raiseError("only one <arguments> element allowed");
|
||||
@@ -519,8 +512,8 @@ bool ExternalTool::save(QString *errorMessage) const
|
||||
out.writeAttribute(kOutput, stringForOutputHandling(m_outputHandling));
|
||||
out.writeAttribute(kError, stringForOutputHandling(m_errorHandling));
|
||||
out.writeAttribute(kModifiesDocument, QLatin1String(m_modifiesCurrentDocument ? kYes : kNo));
|
||||
foreach (const QString &executable, m_executables)
|
||||
out.writeTextElement(kPath, executable);
|
||||
for (const FilePath &executable : m_executables)
|
||||
out.writeTextElement(kPath, executable.toString());
|
||||
if (!m_arguments.isEmpty())
|
||||
out.writeTextElement(kArguments, m_arguments);
|
||||
if (!m_input.isEmpty())
|
||||
@@ -608,11 +601,12 @@ bool ExternalToolRunner::resolve()
|
||||
|
||||
{
|
||||
// executable
|
||||
QStringList expandedExecutables; /* for error message */
|
||||
foreach (const QString &executable, m_tool->executables()) {
|
||||
QString expanded = expander->expand(executable);
|
||||
FilePaths expandedExecutables; /* for error message */
|
||||
const FilePaths executables = m_tool->executables();
|
||||
for (const FilePath &executable : executables) {
|
||||
FilePath expanded = expander->expand(executable);
|
||||
expandedExecutables.append(expanded);
|
||||
m_resolvedExecutable = m_resolvedEnvironment.searchInPath(expanded);
|
||||
m_resolvedExecutable = m_resolvedEnvironment.searchInPath(expanded.path());
|
||||
if (!m_resolvedExecutable.isEmpty())
|
||||
break;
|
||||
}
|
||||
@@ -620,7 +614,8 @@ bool ExternalToolRunner::resolve()
|
||||
m_hasError = true;
|
||||
for (int i = 0; i < expandedExecutables.size(); ++i) {
|
||||
m_errorString += tr("Could not find executable for \"%1\" (expanded \"%2\")")
|
||||
.arg(m_tool->executables().at(i), expandedExecutables.at(i));
|
||||
.arg(m_tool->executables().at(i).toUserOutput(),
|
||||
expandedExecutables.at(i).toUserOutput());
|
||||
m_errorString += QLatin1Char('\n');
|
||||
}
|
||||
if (!m_errorString.isEmpty())
|
||||
|
@@ -64,7 +64,7 @@ public:
|
||||
OutputHandling errorHandling() const;
|
||||
bool modifiesCurrentDocument() const;
|
||||
|
||||
QStringList executables() const;
|
||||
Utils::FilePaths executables() const;
|
||||
QString arguments() const;
|
||||
QString input() const;
|
||||
Utils::FilePath workingDirectory() const;
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
void setOutputHandling(OutputHandling handling);
|
||||
void setErrorHandling(OutputHandling handling);
|
||||
void setModifiesCurrentDocument(bool modifies);
|
||||
void setExecutables(const QStringList &executables);
|
||||
void setExecutables(const Utils::FilePaths &executables);
|
||||
void setArguments(const QString &arguments);
|
||||
void setInput(const QString &input);
|
||||
void setWorkingDirectory(const Utils::FilePath &workingDirectory);
|
||||
@@ -108,7 +108,7 @@ private:
|
||||
QString m_displayName;
|
||||
QString m_displayCategory;
|
||||
int m_order = -1;
|
||||
QStringList m_executables;
|
||||
Utils::FilePaths m_executables;
|
||||
QString m_arguments;
|
||||
QString m_input;
|
||||
Utils::FilePath m_workingDirectory;
|
||||
|
@@ -298,7 +298,8 @@ static const HelpItem::Links getBestLink(const HelpItem::Links &links)
|
||||
// documentation, that we only return the Qt5 link even though the Qt5 and Qt4 URLs look
|
||||
// different.
|
||||
QVersionNumber highestVersion;
|
||||
HelpItem::Link bestLink;
|
||||
// Default to first link if version extraction failed, possibly because it is not a Qt doc link
|
||||
HelpItem::Link bestLink = links.front();
|
||||
for (const HelpItem::Link &link : links) {
|
||||
const QVersionNumber version = extractVersion(link.second).second;
|
||||
if (version > highestVersion) {
|
||||
|
@@ -477,7 +477,7 @@ bool CheckSymbols::visit(NamespaceAST *ast)
|
||||
if (!tok.generated()) {
|
||||
int line, column;
|
||||
getTokenStartPosition(ast->identifier_token, &line, &column);
|
||||
Result use(line, column, tok.utf16chars(), SemanticHighlighter::TypeUse);
|
||||
Result use(line, column, tok.utf16chars(), SemanticHighlighter::NamespaceUse);
|
||||
addUse(use);
|
||||
}
|
||||
}
|
||||
@@ -1221,7 +1221,15 @@ void CheckSymbols::addType(ClassOrNamespace *b, NameAST *ast)
|
||||
int line, column;
|
||||
getTokenStartPosition(startToken, &line, &column);
|
||||
const unsigned length = tok.utf16chars();
|
||||
const Result use(line, column, length, SemanticHighlighter::TypeUse);
|
||||
Kind kind = SemanticHighlighter::TypeUse;
|
||||
const QList<Symbol *> &symbols = b->symbols();
|
||||
for (const Symbol * const s : symbols) {
|
||||
if (s->isNamespace()) {
|
||||
kind = SemanticHighlighter::NamespaceUse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const Result use(line, column, length, kind);
|
||||
addUse(use);
|
||||
}
|
||||
|
||||
@@ -1266,6 +1274,8 @@ bool CheckSymbols::maybeAddTypeOrStatic(const QList<LookupItem> &candidates, Nam
|
||||
Kind kind = SemanticHighlighter::TypeUse;
|
||||
if (c->enclosingEnum() != nullptr)
|
||||
kind = SemanticHighlighter::EnumerationUse;
|
||||
else if (c->isNamespace())
|
||||
kind = SemanticHighlighter::NamespaceUse;
|
||||
else if (c->isStatic())
|
||||
// treat static variable as a field(highlighting)
|
||||
kind = SemanticHighlighter::FieldUse;
|
||||
@@ -1305,7 +1315,8 @@ bool CheckSymbols::maybeAddField(const QList<LookupItem> &candidates, NameAST *a
|
||||
getTokenStartPosition(startToken, &line, &column);
|
||||
const unsigned length = tok.utf16chars();
|
||||
|
||||
const Result use(line, column, length, SemanticHighlighter::FieldUse);
|
||||
const Result use(line, column, length, c->isStatic()
|
||||
? SemanticHighlighter::StaticFieldUse : SemanticHighlighter::FieldUse);
|
||||
addUse(use);
|
||||
|
||||
return true;
|
||||
@@ -1359,12 +1370,15 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
|
||||
continue; // TODO: add diagnostic messages and color call-operators calls too?
|
||||
|
||||
const bool isVirtual = funTy->isVirtual();
|
||||
const bool isStaticMember = funTy->isStatic() && funTy->enclosingClass();
|
||||
Kind matchingKind;
|
||||
if (functionKind == FunctionDeclaration) {
|
||||
matchingKind = isVirtual ? SemanticHighlighter::VirtualFunctionDeclarationUse
|
||||
: isStaticMember ? SemanticHighlighter::StaticMethodDeclarationUse
|
||||
: SemanticHighlighter::FunctionDeclarationUse;
|
||||
} else {
|
||||
matchingKind = isVirtual ? SemanticHighlighter::VirtualMethodUse
|
||||
: isStaticMember ? SemanticHighlighter::StaticMethodUse
|
||||
: SemanticHighlighter::FunctionUse;
|
||||
}
|
||||
if (argumentCount < funTy->minimumArgumentCount()) {
|
||||
|
@@ -326,6 +326,20 @@ void DoxygenTest::testBasic_data()
|
||||
"};\n"
|
||||
);
|
||||
|
||||
QTest::newRow("classTemplate") << _(
|
||||
"bool preventFolding;\n"
|
||||
"/**|\n"
|
||||
"template<typename T> class C {\n"
|
||||
"};\n"
|
||||
) << _(
|
||||
"bool preventFolding;\n"
|
||||
"/**\n"
|
||||
" * @brief The C class\n"
|
||||
" */\n"
|
||||
"template<typename T> class C {\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
QTest::newRow("continuation_after_text_in_first_line") << _(
|
||||
"bool preventFolding;\n"
|
||||
"/*! leading comment|\n"
|
||||
|
@@ -141,6 +141,9 @@ QString DoxygenGenerator::generate(QTextCursor cursor,
|
||||
|
||||
QString DoxygenGenerator::generate(QTextCursor cursor, DeclarationAST *decl)
|
||||
{
|
||||
if (const TemplateDeclarationAST * const templDecl = decl->asTemplateDeclaration())
|
||||
decl = templDecl->declaration;
|
||||
|
||||
SpecifierAST *spec = nullptr;
|
||||
DeclaratorAST *decltr = nullptr;
|
||||
if (SimpleDeclarationAST *simpleDecl = decl->asSimpleDeclaration()) {
|
||||
|
@@ -316,6 +316,7 @@ void SemanticHighlighter::updateFormatMapFromFontSettings()
|
||||
const FontSettings &fs = m_baseTextDocument->fontSettings();
|
||||
|
||||
m_formatMap[TypeUse] = fs.toTextCharFormat(C_TYPE);
|
||||
m_formatMap[NamespaceUse] = fs.toTextCharFormat(C_NAMESPACE);
|
||||
m_formatMap[LocalUse] = fs.toTextCharFormat(C_LOCAL);
|
||||
m_formatMap[FieldUse] = fs.toTextCharFormat(C_FIELD);
|
||||
m_formatMap[EnumerationUse] = fs.toTextCharFormat(C_ENUMERATION);
|
||||
@@ -328,6 +329,12 @@ void SemanticHighlighter::updateFormatMapFromFontSettings()
|
||||
m_formatMap[VirtualFunctionDeclarationUse] =
|
||||
fs.toTextCharFormat(TextStyles::mixinStyle(C_VIRTUAL_METHOD, C_DECLARATION));
|
||||
m_formatMap[PseudoKeywordUse] = fs.toTextCharFormat(C_KEYWORD);
|
||||
m_formatMap[StaticFieldUse]
|
||||
= fs.toTextCharFormat(TextStyles::mixinStyle(C_FIELD, C_STATIC_MEMBER));
|
||||
m_formatMap[StaticMethodUse]
|
||||
= fs.toTextCharFormat(TextStyles::mixinStyle(C_FUNCTION, C_STATIC_MEMBER));
|
||||
m_formatMap[StaticMethodDeclarationUse] = fs.toTextCharFormat(
|
||||
TextStyles::mixinStyle(C_FUNCTION, {C_DECLARATION, C_STATIC_MEMBER}));
|
||||
}
|
||||
|
||||
} // namespace CppEditor
|
||||
|
@@ -48,6 +48,7 @@ public:
|
||||
enum Kind {
|
||||
Unknown = 0,
|
||||
TypeUse,
|
||||
NamespaceUse,
|
||||
LocalUse,
|
||||
FieldUse,
|
||||
EnumerationUse,
|
||||
@@ -58,6 +59,9 @@ public:
|
||||
PseudoKeywordUse,
|
||||
FunctionDeclarationUse,
|
||||
VirtualFunctionDeclarationUse,
|
||||
StaticFieldUse,
|
||||
StaticMethodUse,
|
||||
StaticMethodDeclarationUse,
|
||||
AngleBracketOpen,
|
||||
AngleBracketClose,
|
||||
DoubleAngleBracketClose,
|
||||
|
@@ -57,8 +57,11 @@
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/messagebox.h>
|
||||
#include <projectexplorer/taskhub.h>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <qtsupport/qtversionmanager.h>
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
#include <utils/checkablemessagebox.h>
|
||||
#include <utils/consoleprocess.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
@@ -2243,6 +2246,60 @@ static inline bool checkCommandToken(const QString &tokenPrefix, const QString &
|
||||
return ok;
|
||||
}
|
||||
|
||||
// look for Qt Core Debug module to check whether it is sdk provided
|
||||
// and the pdb files are installed in a path discoverable by the debugger
|
||||
void CdbEngine::checkQtSdkPdbFiles(const QString &module)
|
||||
{
|
||||
const QRegularExpression qtCoreModuleRegExp("(Qt\\dCored).dll");
|
||||
const QRegularExpressionMatch match = qtCoreModuleRegExp.match(module);
|
||||
if (!match.hasMatch())
|
||||
return;
|
||||
const FilePath modulePath = FilePath::fromUserInput(module).parentDir();
|
||||
QtSupport::BaseQtVersion *version = QtSupport::QtVersionManager::version(
|
||||
[modulePath](const QtSupport::BaseQtVersion *version) {
|
||||
return version->isAutodetected() && version->binPath() == modulePath;
|
||||
});
|
||||
if (!version)
|
||||
return;
|
||||
|
||||
const QString qtCoreModuleName = match.captured(1);
|
||||
// Check the usual location of pdb files to avoid the more expensive part of asking cdb
|
||||
const FilePath pdbPath = modulePath.pathAppended(qtCoreModuleName + ".pdb");
|
||||
if (pdbPath.exists())
|
||||
return;
|
||||
|
||||
// If there are no pdb files in the usual location, check whether the user has setup the symbol
|
||||
// path in order to find the debug symbols.
|
||||
// But first we need to load the symbols in order to check whether the pdb files can be found
|
||||
runCommand({"ld " + qtCoreModuleName, BuiltinCommand});
|
||||
DebuggerCommand cmd;
|
||||
cmd.function = "lm m " + qtCoreModuleName;
|
||||
cmd.callback = [this, qtName = version->displayName()](const DebuggerResponse &response) {
|
||||
if (response.data.m_data.contains("private pdb symbols"))
|
||||
return;
|
||||
|
||||
const QString message
|
||||
= tr("The installed %1 is missing debug information files.\n"
|
||||
"Locals and Expression might not be able to display all Qt Types in a "
|
||||
"human readable format.\n\n"
|
||||
"Please install the \"Qt Debug Information Files\" Package from the "
|
||||
"Maintenance Tool for this Qt installation to get all relevant "
|
||||
"symbols for the debugger.")
|
||||
.arg(qtName);
|
||||
|
||||
CheckableMessageBox::doNotShowAgainInformation(
|
||||
Core::ICore::dialogParent(),
|
||||
tr("Missing Qt Debug Information"),
|
||||
message,
|
||||
Core::ICore::settings(),
|
||||
"CdbQtSdkPdbHint");
|
||||
|
||||
showMessage("Missing Qt Debug Information Files package for " + qtName, LogMisc);
|
||||
};
|
||||
cmd.flags = BuiltinCommand;
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void CdbEngine::parseOutputLine(QString line)
|
||||
{
|
||||
// The hooked output callback in the extension suppresses prompts,
|
||||
@@ -2351,8 +2408,11 @@ void CdbEngine::parseOutputLine(QString line)
|
||||
// output(32): ModLoad: 00007ffb 00007ffb C:\Windows\system32\KERNEL32.DLL
|
||||
const QRegularExpression moduleRegExp("[0-9a-fA-F]+(`[0-9a-fA-F]+)? [0-9a-fA-F]+(`[0-9a-fA-F]+)? (.*)");
|
||||
const QRegularExpressionMatch match = moduleRegExp.match(line);
|
||||
if (match.hasMatch())
|
||||
showStatusMessage(tr("Module loaded: %1").arg(match.captured(3).trimmed()), 3000);
|
||||
if (match.hasMatch()) {
|
||||
const QString module = match.captured(3).trimmed();
|
||||
showStatusMessage(tr("Module loaded: %1").arg(module), 3000);
|
||||
checkQtSdkPdbFiles(module);
|
||||
}
|
||||
} else {
|
||||
showMessage(line, LogMisc);
|
||||
}
|
||||
|
@@ -194,6 +194,7 @@ private:
|
||||
int elapsedLogTime();
|
||||
unsigned parseStackTrace(const GdbMi &data, bool sourceStepInto);
|
||||
void mergeStartParametersSourcePathMap();
|
||||
void checkQtSdkPdbFiles(const QString &module);
|
||||
|
||||
const QString m_tokenPrefix;
|
||||
void handleSetupFailure(const QString &errorMessage);
|
||||
|
@@ -74,6 +74,7 @@
|
||||
#include <texteditor/fontsettings.h>
|
||||
|
||||
#include <utils/basetreeview.h>
|
||||
#include <utils/checkablemessagebox.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/processhandle.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -1096,7 +1097,7 @@ void DebuggerEngine::gotoLocation(const Location &loc)
|
||||
showMessage("CANNOT GO TO THIS LOCATION");
|
||||
return;
|
||||
}
|
||||
const QString file = loc.fileName().toString();
|
||||
const FilePath file = loc.fileName();
|
||||
const int line = loc.lineNumber();
|
||||
bool newEditor = false;
|
||||
IEditor *editor = EditorManager::openEditor(file,
|
||||
@@ -2729,27 +2730,34 @@ Context CppDebuggerEngine::languageContext() const
|
||||
|
||||
void CppDebuggerEngine::validateRunParameters(DebuggerRunParameters &rp)
|
||||
{
|
||||
static const QString warnOnInappropriateDebuggerKey = "DebuggerWarnOnInappropriateDebugger";
|
||||
QtcSettings *coreSettings = Core::ICore::settings();
|
||||
|
||||
const bool warnOnRelease = debuggerSettings()->warnOnReleaseBuilds.value()
|
||||
&& rp.toolChainAbi.osFlavor() != Abi::AndroidLinuxFlavor;
|
||||
bool warnOnInappropriateDebugger = false;
|
||||
QString detailedWarning;
|
||||
switch (rp.toolChainAbi.binaryFormat()) {
|
||||
case Abi::PEFormat: {
|
||||
QString preferredDebugger;
|
||||
if (rp.toolChainAbi.osFlavor() == Abi::WindowsMSysFlavor) {
|
||||
if (rp.cppEngineType == CdbEngineType)
|
||||
preferredDebugger = "GDB";
|
||||
} else if (rp.cppEngineType != CdbEngineType) {
|
||||
// osFlavor() is MSVC, so the recommended debugger is CDB
|
||||
preferredDebugger = "CDB";
|
||||
}
|
||||
if (!preferredDebugger.isEmpty()) {
|
||||
warnOnInappropriateDebugger = true;
|
||||
detailedWarning = DebuggerEngine::tr(
|
||||
"The inferior is in the Portable Executable format.\n"
|
||||
"Selecting %1 as debugger would improve the debugging "
|
||||
"experience for this binary format.").arg(preferredDebugger);
|
||||
break;
|
||||
if (CheckableMessageBox::shouldAskAgain(coreSettings, warnOnInappropriateDebuggerKey)) {
|
||||
QString preferredDebugger;
|
||||
if (rp.toolChainAbi.osFlavor() == Abi::WindowsMSysFlavor) {
|
||||
if (rp.cppEngineType == CdbEngineType)
|
||||
preferredDebugger = "GDB";
|
||||
} else if (rp.cppEngineType != CdbEngineType && rp.cppEngineType != LldbEngineType) {
|
||||
// osFlavor() is MSVC, so the recommended debugger is still CDB,
|
||||
// but don't warn for LLDB which starts to be usable, too.
|
||||
preferredDebugger = "CDB";
|
||||
}
|
||||
if (!preferredDebugger.isEmpty()) {
|
||||
warnOnInappropriateDebugger = true;
|
||||
detailedWarning = DebuggerEngine::tr(
|
||||
"The inferior is in the Portable Executable format.\n"
|
||||
"Selecting %1 as debugger would improve the debugging "
|
||||
"experience for this binary format.")
|
||||
.arg(preferredDebugger);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (warnOnRelease
|
||||
&& rp.cppEngineType == CdbEngineType
|
||||
@@ -2771,13 +2779,15 @@ void CppDebuggerEngine::validateRunParameters(DebuggerRunParameters &rp)
|
||||
break;
|
||||
}
|
||||
case Abi::ElfFormat: {
|
||||
if (rp.cppEngineType == CdbEngineType) {
|
||||
warnOnInappropriateDebugger = true;
|
||||
detailedWarning = DebuggerEngine::tr(
|
||||
"The inferior is in the ELF format.\n"
|
||||
"Selecting GDB or LLDB as debugger would improve the debugging "
|
||||
"experience for this binary format.");
|
||||
break;
|
||||
if (CheckableMessageBox::shouldAskAgain(coreSettings, warnOnInappropriateDebuggerKey)) {
|
||||
if (rp.cppEngineType == CdbEngineType) {
|
||||
warnOnInappropriateDebugger = true;
|
||||
detailedWarning = DebuggerEngine::tr(
|
||||
"The inferior is in the ELF format.\n"
|
||||
"Selecting GDB or LLDB as debugger would improve the debugging "
|
||||
"experience for this binary format.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ElfReader reader(rp.symbolFile);
|
||||
@@ -2876,11 +2886,16 @@ void CppDebuggerEngine::validateRunParameters(DebuggerRunParameters &rp)
|
||||
return;
|
||||
}
|
||||
if (warnOnInappropriateDebugger) {
|
||||
AsynchronousMessageBox::information(DebuggerEngine::tr("Warning"),
|
||||
DebuggerEngine::tr("The selected debugger may be inappropriate for the inferior.\n"
|
||||
"Examining symbols and setting breakpoints by file name and line number "
|
||||
"may fail.\n")
|
||||
+ '\n' + detailedWarning);
|
||||
CheckableMessageBox::doNotShowAgainInformation(
|
||||
Core::ICore::dialogParent(),
|
||||
DebuggerEngine::tr("Warning"),
|
||||
DebuggerEngine::tr(
|
||||
"The selected debugger may be inappropriate for the inferior.\n"
|
||||
"Examining symbols and setting breakpoints by file name and line number "
|
||||
"may fail.\n")
|
||||
+ '\n' + detailedWarning,
|
||||
Core::ICore::settings(),
|
||||
warnOnInappropriateDebuggerKey);
|
||||
} else if (warnOnRelease) {
|
||||
AsynchronousMessageBox::information(DebuggerEngine::tr("Warning"),
|
||||
DebuggerEngine::tr("This does not seem to be a \"Debug\" build.\n"
|
||||
|
@@ -150,7 +150,8 @@ void DebuggerItem::reinitializeFromFile(const Environment &sysEnv, QString *erro
|
||||
// except for the experimental LLDB-MI which insists on --version.
|
||||
QString version = "-version";
|
||||
m_lastModified = m_command.lastModified();
|
||||
if (m_command.baseName().toLower().contains("lldb-mi"))
|
||||
if (m_command.baseName().toLower().contains("lldb-mi")
|
||||
|| m_command.baseName().startsWith("LLDBFrontend")) // Comes with Android Studio
|
||||
version = "--version";
|
||||
|
||||
// We don't need to start the uVision executable to
|
||||
@@ -229,15 +230,16 @@ void DebuggerItem::reinitializeFromFile(const Environment &sysEnv, QString *erro
|
||||
//! \note If unable to determine the GDB ABI, no ABI is appended to m_abis here.
|
||||
return;
|
||||
}
|
||||
if (output.startsWith("lldb") || output.startsWith("LLDB")) {
|
||||
if (output.contains("lldb") || output.startsWith("LLDB")) {
|
||||
m_engineType = LldbEngineType;
|
||||
m_abis = Abi::abisOfBinary(m_command);
|
||||
|
||||
// Version
|
||||
// Self-build binaries also emit clang and llvm revision.
|
||||
const QString line = output.split('\n')[0];
|
||||
if (line.startsWith(("lldb version "))) { // Linux typically.
|
||||
int pos1 = int(strlen("lldb version "));
|
||||
const QString nonMacOSPrefix = "lldb version ";
|
||||
if (line.contains(nonMacOSPrefix)) { // Linux typically, or some Windows builds.
|
||||
int pos1 = line.indexOf(nonMacOSPrefix) + nonMacOSPrefix.length();
|
||||
int pos2 = line.indexOf(' ', pos1);
|
||||
m_version = line.mid(pos1, pos2 - pos1);
|
||||
} else if (line.startsWith("lldb-") || line.startsWith("LLDB-")) { // Mac typically.
|
||||
|
@@ -58,11 +58,12 @@
|
||||
#include <QJsonArray>
|
||||
|
||||
using namespace Core;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
PdbEngine::PdbEngine()
|
||||
PdbEngine::PdbEngine() : m_proc(ProcessMode::Writer)
|
||||
{
|
||||
setObjectName("PdbEngine");
|
||||
setDebuggerName("PDB");
|
||||
@@ -117,13 +118,10 @@ void PdbEngine::setupEngine()
|
||||
m_interpreter = runParameters().interpreter;
|
||||
QString bridge = ICore::resourcePath("debugger/pdbbridge.py").toString();
|
||||
|
||||
connect(&m_proc, &QProcess::errorOccurred, this, &PdbEngine::handlePdbError);
|
||||
connect(&m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
||||
this, &PdbEngine::handlePdbFinished);
|
||||
connect(&m_proc, &QProcess::readyReadStandardOutput,
|
||||
this, &PdbEngine::readPdbStandardOutput);
|
||||
connect(&m_proc, &QProcess::readyReadStandardError,
|
||||
this, &PdbEngine::readPdbStandardError);
|
||||
connect(&m_proc, &QtcProcess::errorOccurred, this, &PdbEngine::handlePdbError);
|
||||
connect(&m_proc, &QtcProcess::finished, this, &PdbEngine::handlePdbFinished);
|
||||
connect(&m_proc, &QtcProcess::readyReadStandardOutput, this, &PdbEngine::readPdbStandardOutput);
|
||||
connect(&m_proc, &QtcProcess::readyReadStandardError, this, &PdbEngine::readPdbStandardError);
|
||||
|
||||
QFile scriptFile(runParameters().mainScript);
|
||||
if (!scriptFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
||||
@@ -134,10 +132,11 @@ void PdbEngine::setupEngine()
|
||||
}
|
||||
|
||||
QStringList args = {bridge, scriptFile.fileName()};
|
||||
args.append(Utils::ProcessArgs::splitArgs(runParameters().inferior.workingDirectory.path()));
|
||||
args.append(ProcessArgs::splitArgs(runParameters().inferior.workingDirectory.path()));
|
||||
showMessage("STARTING " + m_interpreter + ' ' + args.join(' '));
|
||||
m_proc.setEnvironment(runParameters().debugger.environment.toStringList());
|
||||
m_proc.start(m_interpreter, args);
|
||||
m_proc.setEnvironment(runParameters().debugger.environment);
|
||||
m_proc.setCommand({ FilePath::fromString(m_interpreter), args });
|
||||
m_proc.start();
|
||||
|
||||
if (!m_proc.waitForStarted()) {
|
||||
const QString msg = tr("Unable to start pdb \"%1\": %2")
|
||||
@@ -346,7 +345,7 @@ void PdbEngine::refreshState(const GdbMi &reportedState)
|
||||
void PdbEngine::refreshLocation(const GdbMi &reportedLocation)
|
||||
{
|
||||
StackFrame frame;
|
||||
frame.file = Utils::FilePath::fromString(reportedLocation["file"].data());
|
||||
frame.file = FilePath::fromString(reportedLocation["file"].data());
|
||||
frame.line = reportedLocation["line"].toInt();
|
||||
frame.usable = frame.file.isReadableFile();
|
||||
if (state() == InferiorRunOk) {
|
||||
@@ -435,9 +434,10 @@ QString PdbEngine::errorMessage(QProcess::ProcessError error) const
|
||||
}
|
||||
}
|
||||
|
||||
void PdbEngine::handlePdbFinished(int code, QProcess::ExitStatus type)
|
||||
void PdbEngine::handlePdbFinished()
|
||||
{
|
||||
showMessage(QString("PDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
|
||||
showMessage(QString("PDB PROCESS FINISHED, status %1, code %2")
|
||||
.arg(m_proc.exitStatus()).arg(m_proc.exitCode()));
|
||||
notifyEngineSpontaneousShutdown();
|
||||
}
|
||||
|
||||
@@ -495,10 +495,9 @@ void PdbEngine::handleOutput2(const QString &data)
|
||||
const QString bpnr = line.mid(11, pos1 - 11);
|
||||
const int pos2 = line.lastIndexOf(':');
|
||||
QTC_ASSERT(pos2 != -1, continue);
|
||||
const Utils::FilePath fileName = Utils::FilePath::fromString(
|
||||
line.mid(pos1 + 4, pos2 - pos1 - 4));
|
||||
const FilePath fileName = FilePath::fromString(line.mid(pos1 + 4, pos2 - pos1 - 4));
|
||||
const int lineNumber = line.mid(pos2 + 1).toInt();
|
||||
const Breakpoint bp = Utils::findOrDefault(breakHandler()->breakpoints(), [&](const Breakpoint &bp) {
|
||||
const Breakpoint bp = findOrDefault(breakHandler()->breakpoints(), [&](const Breakpoint &bp) {
|
||||
return bp->parameters().isLocatedAt(fileName, lineNumber, bp->markerFileName())
|
||||
|| bp->requestedParameters().isLocatedAt(fileName, lineNumber, bp->markerFileName());
|
||||
});
|
||||
@@ -535,7 +534,7 @@ void PdbEngine::refreshStack(const GdbMi &stack)
|
||||
for (const GdbMi &item : stack["frames"]) {
|
||||
StackFrame frame;
|
||||
frame.level = item["level"].data();
|
||||
frame.file = Utils::FilePath::fromString(item["file"].data());
|
||||
frame.file = FilePath::fromString(item["file"].data());
|
||||
frame.function = item["function"].data();
|
||||
frame.module = item["function"].data();
|
||||
frame.line = item["line"].toInt();
|
||||
|
@@ -26,8 +26,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <debugger/debuggerengine.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <QProcess>
|
||||
#include <QVariant>
|
||||
|
||||
namespace Debugger {
|
||||
@@ -100,7 +100,7 @@ private:
|
||||
QString errorMessage(QProcess::ProcessError error) const;
|
||||
bool hasCapability(unsigned cap) const override;
|
||||
|
||||
void handlePdbFinished(int, QProcess::ExitStatus status);
|
||||
void handlePdbFinished();
|
||||
void handlePdbError(QProcess::ProcessError error);
|
||||
void readPdbStandardOutput();
|
||||
void readPdbStandardError();
|
||||
@@ -111,7 +111,7 @@ private:
|
||||
void updateLocals() override;
|
||||
|
||||
QString m_inbuffer;
|
||||
QProcess m_proc;
|
||||
Utils::QtcProcess m_proc;
|
||||
QString m_interpreter;
|
||||
};
|
||||
|
||||
|
@@ -50,7 +50,12 @@ bool isIntType(const QString &type)
|
||||
case 'c':
|
||||
return type == "char";
|
||||
case 'i':
|
||||
return type == "int";
|
||||
return type.startsWith("int") &&
|
||||
( type == "int"
|
||||
|| type == "int8_t"
|
||||
|| type == "int16_t"
|
||||
|| type == "int32_t"
|
||||
|| type == "int64_t");
|
||||
case 'l':
|
||||
return type == "long"
|
||||
|| type == "long int"
|
||||
@@ -86,7 +91,12 @@ bool isIntType(const QString &type)
|
||||
|| type == "unsigned long"
|
||||
|| type == "unsigned long int"
|
||||
|| type == "unsigned long long"
|
||||
|| type == "unsigned long long int"));
|
||||
|| type == "unsigned long long int"))
|
||||
|| (type.startsWith("uint") &&
|
||||
( type == "uint8_t"
|
||||
|| type == "uint16_t"
|
||||
|| type == "uint32_t"
|
||||
|| type == "uint64_t"));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@@ -718,10 +718,10 @@ static QString formattedValue(const WatchItem *item)
|
||||
|
||||
// Append quoted, printable character also for decimal.
|
||||
// FIXME: This is unreliable.
|
||||
if (item->type.endsWith("char")) {
|
||||
if (item->type.endsWith("char") || item->type.endsWith("int8_t")) {
|
||||
bool ok;
|
||||
const int code = item->value.toInt(&ok);
|
||||
bool isUnsigned = item->type == "unsigned char" || item->type == "uchar";
|
||||
bool isUnsigned = item->type == "unsigned char" || item->type == "uchar" || item->type == "uint8_t";
|
||||
if (ok)
|
||||
return reformatCharacter(code, 1, !isUnsigned);
|
||||
} else if (item->type.endsWith("wchar_t")) {
|
||||
|
@@ -59,12 +59,12 @@
|
||||
#include "fakevimtr.h"
|
||||
|
||||
#include <utils/optional.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QTextStream>
|
||||
#include <QTimer>
|
||||
@@ -866,17 +866,10 @@ static QString fromLocalEncoding(const QByteArray &data)
|
||||
|
||||
static QString getProcessOutput(const QString &command, const QString &input)
|
||||
{
|
||||
QProcess proc;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||
QStringList arguments = QProcess::splitCommand(command);
|
||||
QString executable = arguments.takeFirst();
|
||||
proc.start(executable, arguments);
|
||||
#else
|
||||
proc.start(command);
|
||||
#endif
|
||||
proc.waitForStarted();
|
||||
proc.write(toLocalEncoding(input));
|
||||
proc.closeWriteChannel();
|
||||
Utils::QtcProcess proc;
|
||||
proc.setCommand(Utils::CommandLine::fromUserInput(command));
|
||||
proc.setWriteData(toLocalEncoding(input));
|
||||
proc.start();
|
||||
|
||||
// FIXME: Process should be interruptable by user.
|
||||
// Solution is to create a QObject for each process and emit finished state.
|
||||
|
@@ -412,12 +412,20 @@ void SemanticTokenSupport::handleSemanticTokensDelta(
|
||||
|
||||
auto it = data.begin();
|
||||
const auto end = data.end();
|
||||
qCDebug(LOGLSPHIGHLIGHT) << "Edit Tokens for " << filePath;
|
||||
qCDebug(LOGLSPHIGHLIGHT) << "Data before edit " << data;
|
||||
for (const SemanticTokensEdit &edit : qAsConst(edits)) {
|
||||
if (edit.start() > data.size()) // prevent edits after the previously reported data
|
||||
return;
|
||||
for (const auto start = data.begin() + edit.start(); it < start; ++it)
|
||||
newData.append(*it);
|
||||
newData.append(edit.data().value_or(QList<int>()));
|
||||
const Utils::optional<QList<int>> editData = edit.data();
|
||||
if (editData.has_value()) {
|
||||
newData.append(editData.value());
|
||||
qCDebug(LOGLSPHIGHLIGHT) << edit.start() << edit.deleteCount() << editData.value();
|
||||
} else {
|
||||
qCDebug(LOGLSPHIGHLIGHT) << edit.start() << edit.deleteCount();
|
||||
}
|
||||
int deleteCount = edit.deleteCount();
|
||||
if (deleteCount > std::distance(it, end)) {
|
||||
qCDebug(LOGLSPHIGHLIGHT)
|
||||
@@ -434,6 +442,7 @@ void SemanticTokenSupport::handleSemanticTokensDelta(
|
||||
for (; it != end; ++it)
|
||||
newData.append(*it);
|
||||
|
||||
qCDebug(LOGLSPHIGHLIGHT) << "New Data " << newData;
|
||||
tokens.setData(newData);
|
||||
tokens.setResultId(tokensDelta->resultId());
|
||||
} else {
|
||||
@@ -478,6 +487,14 @@ void SemanticTokenSupport::highlight(const Utils::FilePath &filePath)
|
||||
expandedToken.length = token.length;
|
||||
expandedTokens << expandedToken;
|
||||
};
|
||||
if (LOGLSPHIGHLIGHT().isDebugEnabled()) {
|
||||
qCDebug(LOGLSPHIGHLIGHT) << "Expanded Tokens for " << filePath;
|
||||
for (const ExpandedSemanticToken &token : qAsConst(expandedTokens)) {
|
||||
qCDebug(LOGLSPHIGHLIGHT)
|
||||
<< token.line << token.column << token.length << token.type << token.modifiers;
|
||||
}
|
||||
}
|
||||
|
||||
m_tokensHandler(doc, expandedTokens, versionedTokens.version);
|
||||
return;
|
||||
}
|
||||
|
@@ -134,7 +134,6 @@ extend_qtc_plugin(QmlDesigner
|
||||
modelnodeoperations.cpp modelnodeoperations.h
|
||||
formatoperation.cpp formatoperation.h
|
||||
navigation2d.cpp navigation2d.h
|
||||
gestures.cpp gestures.h
|
||||
qmldesignericonprovider.cpp qmldesignericonprovider.h
|
||||
selectioncontext.cpp selectioncontext.h
|
||||
theme.cpp theme.h
|
||||
|
@@ -5,7 +5,6 @@ SOURCES += addimagesdialog.cpp
|
||||
SOURCES += changestyleaction.cpp
|
||||
SOURCES += theme.cpp
|
||||
SOURCES += findimplementation.cpp
|
||||
SOURCES += gestures.cpp
|
||||
SOURCES += addsignalhandlerdialog.cpp
|
||||
SOURCES += layoutingridlayout.cpp
|
||||
SOURCES += abstractactiongroup.cpp
|
||||
@@ -27,7 +26,6 @@ HEADERS += addimagesdialog.h
|
||||
HEADERS += changestyleaction.h
|
||||
HEADERS += theme.h
|
||||
HEADERS += findimplementation.h
|
||||
HEADERS += gestures.h
|
||||
HEADERS += addsignalhandlerdialog.h
|
||||
HEADERS += layoutingridlayout.h
|
||||
HEADERS += abstractactiongroup.h
|
||||
|
@@ -1,156 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Design Tooling
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "gestures.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
Qt::GestureType TwoFingerSwipe::m_type = static_cast<Qt::GestureType>(0);
|
||||
|
||||
TwoFingerSwipe::TwoFingerSwipe() {}
|
||||
|
||||
Qt::GestureType TwoFingerSwipe::type()
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
void TwoFingerSwipe::registerRecognizer()
|
||||
{
|
||||
m_type = QGestureRecognizer::registerRecognizer(new TwoFingerSwipeRecognizer());
|
||||
}
|
||||
|
||||
QPointF TwoFingerSwipe::direction() const
|
||||
{
|
||||
return m_current.center() - m_last.center();
|
||||
}
|
||||
|
||||
void TwoFingerSwipe::reset()
|
||||
{
|
||||
m_start = QLineF();
|
||||
m_current = QLineF();
|
||||
m_last = QLineF();
|
||||
}
|
||||
|
||||
QGestureRecognizer::Result TwoFingerSwipe::begin(QTouchEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
return QGestureRecognizer::MayBeGesture;
|
||||
}
|
||||
|
||||
QGestureRecognizer::Result TwoFingerSwipe::update(QTouchEvent *event)
|
||||
{
|
||||
if (event->touchPoints().size() != 2) {
|
||||
if (state() == Qt::NoGesture)
|
||||
return QGestureRecognizer::Ignore;
|
||||
else
|
||||
return QGestureRecognizer::FinishGesture;
|
||||
}
|
||||
|
||||
QTouchEvent::TouchPoint p0 = event->touchPoints().at(0);
|
||||
QTouchEvent::TouchPoint p1 = event->touchPoints().at(1);
|
||||
|
||||
QLineF line(p0.scenePos(), p1.screenPos());
|
||||
|
||||
if (m_start.isNull()) {
|
||||
m_start = line;
|
||||
m_current = line;
|
||||
m_last = line;
|
||||
} else {
|
||||
auto deltaLength = line.length() - m_current.length();
|
||||
auto deltaCenter = QLineF(line.center(), m_current.center()).length();
|
||||
if (deltaLength > deltaCenter)
|
||||
return QGestureRecognizer::CancelGesture;
|
||||
|
||||
m_last = m_current;
|
||||
m_current = line;
|
||||
}
|
||||
|
||||
setHotSpot(m_current.center());
|
||||
|
||||
return QGestureRecognizer::TriggerGesture;
|
||||
}
|
||||
|
||||
QGestureRecognizer::Result TwoFingerSwipe::end(QTouchEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
bool finish = state() != Qt::NoGesture;
|
||||
|
||||
reset();
|
||||
|
||||
if (finish)
|
||||
return QGestureRecognizer::FinishGesture;
|
||||
else
|
||||
return QGestureRecognizer::CancelGesture;
|
||||
}
|
||||
|
||||
TwoFingerSwipeRecognizer::TwoFingerSwipeRecognizer()
|
||||
: QGestureRecognizer()
|
||||
{}
|
||||
|
||||
QGesture *TwoFingerSwipeRecognizer::create(QObject *target)
|
||||
{
|
||||
if (target && target->isWidgetType())
|
||||
qobject_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
|
||||
return new TwoFingerSwipe;
|
||||
}
|
||||
|
||||
QGestureRecognizer::Result TwoFingerSwipeRecognizer::recognize(QGesture *gesture,
|
||||
QObject *,
|
||||
QEvent *event)
|
||||
{
|
||||
if (gesture->gestureType() != TwoFingerSwipe::type())
|
||||
return QGestureRecognizer::Ignore;
|
||||
|
||||
TwoFingerSwipe *swipe = static_cast<TwoFingerSwipe *>(gesture);
|
||||
QTouchEvent *touch = static_cast<QTouchEvent *>(event);
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::TouchBegin:
|
||||
return swipe->begin(touch);
|
||||
|
||||
case QEvent::TouchUpdate:
|
||||
return swipe->update(touch);
|
||||
|
||||
case QEvent::TouchEnd:
|
||||
return swipe->end(touch);
|
||||
|
||||
default:
|
||||
return QGestureRecognizer::Ignore;
|
||||
}
|
||||
}
|
||||
|
||||
void TwoFingerSwipeRecognizer::reset(QGesture *gesture)
|
||||
{
|
||||
if (gesture->gestureType() == TwoFingerSwipe::type()) {
|
||||
TwoFingerSwipe *swipe = static_cast<TwoFingerSwipe *>(gesture);
|
||||
swipe->reset();
|
||||
}
|
||||
QGestureRecognizer::reset(gesture);
|
||||
}
|
||||
|
||||
} // End namespace QmlDesigner.
|
@@ -1,72 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Design Tooling
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QGesture>
|
||||
#include <QGestureRecognizer>
|
||||
#include <QLineF>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QTouchEvent)
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class TwoFingerSwipe : public QGesture
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TwoFingerSwipe();
|
||||
|
||||
static Qt::GestureType type();
|
||||
static void registerRecognizer();
|
||||
|
||||
QPointF direction() const;
|
||||
|
||||
void reset();
|
||||
QGestureRecognizer::Result begin(QTouchEvent *event);
|
||||
QGestureRecognizer::Result update(QTouchEvent *event);
|
||||
QGestureRecognizer::Result end(QTouchEvent *event);
|
||||
|
||||
private:
|
||||
static Qt::GestureType m_type;
|
||||
|
||||
QLineF m_start;
|
||||
QLineF m_current;
|
||||
QLineF m_last;
|
||||
};
|
||||
|
||||
class TwoFingerSwipeRecognizer : public QGestureRecognizer
|
||||
{
|
||||
public:
|
||||
TwoFingerSwipeRecognizer();
|
||||
|
||||
QGesture *create(QObject *target) override;
|
||||
|
||||
QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event) override;
|
||||
|
||||
void reset(QGesture *gesture) override;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -23,44 +23,38 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
#include "navigation2d.h"
|
||||
#include "gestures.h"
|
||||
|
||||
#include <QGestureEvent>
|
||||
#include <QScrollBar>
|
||||
#include <QWheelEvent>
|
||||
#include <QMetaMethod>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
Navigation2dScrollBar::Navigation2dScrollBar(QWidget *parent)
|
||||
: QScrollBar(parent)
|
||||
{}
|
||||
|
||||
bool Navigation2dScrollBar::postEvent(QEvent *event)
|
||||
void Navigation2dFilter::scroll(const QPointF &direction, QScrollBar *sbx, QScrollBar *sby)
|
||||
{
|
||||
if (event->type() == QEvent::Wheel) {
|
||||
wheelEvent(static_cast<QWheelEvent *>(event));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
auto doScroll = [](QScrollBar *sb, float distance) {
|
||||
if (sb) {
|
||||
// max - min + pageStep = sceneRect.size * scale
|
||||
float d1 = sb->maximum() - sb->minimum();
|
||||
float d2 = d1 + sb->pageStep();
|
||||
|
||||
float val = (distance / d2) * d1;
|
||||
sb->setValue(sb->value() - val);
|
||||
}
|
||||
};
|
||||
|
||||
doScroll(sbx, direction.x());
|
||||
doScroll(sby, direction.y());
|
||||
}
|
||||
|
||||
void Navigation2dScrollBar::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (!event->angleDelta().isNull())
|
||||
QScrollBar::wheelEvent(event);
|
||||
}
|
||||
|
||||
|
||||
Navigation2dFilter::Navigation2dFilter(QWidget *parent, Navigation2dScrollBar *scrollbar)
|
||||
Navigation2dFilter::Navigation2dFilter(QWidget *parent)
|
||||
: QObject(parent)
|
||||
, m_scrollbar(scrollbar)
|
||||
{
|
||||
if (parent) {
|
||||
if (parent)
|
||||
parent->grabGesture(Qt::PinchGesture);
|
||||
if (!scrollbar)
|
||||
parent->grabGesture(TwoFingerSwipe::type());
|
||||
}
|
||||
}
|
||||
|
||||
bool Navigation2dFilter::eventFilter(QObject *object, QEvent *event)
|
||||
@@ -82,34 +76,39 @@ bool Navigation2dFilter::gestureEvent(QGestureEvent *event)
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
} else if (TwoFingerSwipe *swipe = static_cast<TwoFingerSwipe *>(
|
||||
event->gesture(TwoFingerSwipe::type()))) {
|
||||
emit panChanged(swipe->direction());
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Navigation2dFilter::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (m_scrollbar) {
|
||||
if (m_scrollbar->postEvent(event))
|
||||
event->ignore();
|
||||
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
|
||||
emit panChanged(QPointF(event->pixelDelta()));
|
||||
event->accept();
|
||||
return true;
|
||||
} else if (event->source() == Qt::MouseEventNotSynthesized) {
|
||||
if (event->modifiers().testFlag(Qt::ControlModifier)) {
|
||||
if (QPointF angle = event->angleDelta(); !angle.isNull()) {
|
||||
double delta = std::abs(angle.x()) > std::abs(angle.y()) ? angle.x() : angle.y();
|
||||
if (delta > 0)
|
||||
emit zoomIn();
|
||||
else
|
||||
emit zoomOut();
|
||||
event->accept();
|
||||
return true;
|
||||
|
||||
auto zoomInSignal = QMetaMethod::fromSignal(&Navigation2dFilter::zoomIn);
|
||||
bool zoomInConnected = QObject::isSignalConnected(zoomInSignal);
|
||||
|
||||
auto zoomOutSignal = QMetaMethod::fromSignal(&Navigation2dFilter::zoomOut);
|
||||
bool zoomOutConnected = QObject::isSignalConnected(zoomOutSignal);
|
||||
|
||||
if (zoomInConnected && zoomOutConnected) {
|
||||
if (event->modifiers().testFlag(Qt::ControlModifier)) {
|
||||
if (QPointF angle = event->angleDelta(); !angle.isNull()) {
|
||||
double delta = std::abs(angle.x()) > std::abs(angle.y()) ? angle.x() : angle.y();
|
||||
if (delta > 0)
|
||||
emit zoomIn();
|
||||
else
|
||||
emit zoomOut();
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End namespace QmlDesigner.
|
||||
|
@@ -24,27 +24,14 @@
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QObject>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QGestureEvent)
|
||||
QT_FORWARD_DECLARE_CLASS(QScrollBar)
|
||||
QT_FORWARD_DECLARE_CLASS(QWheelEvent)
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class Navigation2dScrollBar : public QScrollBar
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Navigation2dScrollBar(QWidget *parent = nullptr);
|
||||
|
||||
bool postEvent(QEvent *event);
|
||||
|
||||
protected:
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
};
|
||||
|
||||
|
||||
class Navigation2dFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -57,7 +44,9 @@ signals:
|
||||
void zoomOut();
|
||||
|
||||
public:
|
||||
Navigation2dFilter(QWidget *parent = nullptr, Navigation2dScrollBar *scrollbar = nullptr);
|
||||
static void scroll(const QPointF &direction, QScrollBar *sbx, QScrollBar *sby);
|
||||
|
||||
Navigation2dFilter(QWidget *parent);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
@@ -65,7 +54,6 @@ protected:
|
||||
private:
|
||||
bool gestureEvent(QGestureEvent *event);
|
||||
bool wheelEvent(QWheelEvent *event);
|
||||
Navigation2dScrollBar *m_scrollbar = nullptr;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QScrollArea>
|
||||
#include <QSplitter>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
@@ -40,16 +41,20 @@ namespace QmlDesigner {
|
||||
CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_tree(new TreeView(model, this))
|
||||
, m_view(new GraphicsView(model))
|
||||
, m_view(new GraphicsView(model, this))
|
||||
{
|
||||
auto *splitter = new QSplitter;
|
||||
splitter->addWidget(m_tree);
|
||||
splitter->addWidget(m_view);
|
||||
splitter->setStretchFactor(1, 2);
|
||||
|
||||
QScrollArea* area = new QScrollArea;
|
||||
area->setWidget(splitter);
|
||||
area->setWidgetResizable(true);
|
||||
|
||||
auto *box = new QVBoxLayout;
|
||||
box->addWidget(createToolBar(model));
|
||||
box->addWidget(splitter);
|
||||
box->addWidget(area);
|
||||
setLayout(box);
|
||||
|
||||
connect(m_tree, &TreeView::treeItemLocked, model, &CurveEditorModel::setLocked);
|
||||
|
@@ -45,6 +45,18 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
template< typename T >
|
||||
T* nextParentOfType(QWidget* widget)
|
||||
{
|
||||
auto* p = widget->parent();
|
||||
while (p) {
|
||||
if (T* w = qobject_cast<T*>(p))
|
||||
return w;
|
||||
p = p->parent();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
||||
: QGraphicsView(parent)
|
||||
, m_dragging(false)
|
||||
@@ -65,7 +77,7 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
||||
setResizeAnchor(QGraphicsView::NoAnchor);
|
||||
setRenderHint(QPainter::Antialiasing, true);
|
||||
setTransformationAnchor(QGraphicsView::NoAnchor);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||
|
||||
@@ -78,12 +90,19 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
||||
|
||||
connect(m_scene, &GraphicsScene::curveChanged, itemSlot);
|
||||
|
||||
QmlDesigner::Navigation2dFilter *filter = new QmlDesigner::Navigation2dFilter(this);
|
||||
QmlDesigner::Navigation2dFilter *filter = new QmlDesigner::Navigation2dFilter(viewport());
|
||||
connect(filter, &Navigation2dFilter::panChanged, [this](const QPointF &direction) {
|
||||
QScrollBar* verticalBar = nullptr;
|
||||
if (QScrollArea* area = nextParentOfType< QScrollArea >(this))
|
||||
verticalBar = area->verticalScrollBar();
|
||||
Navigation2dFilter::scroll(direction, horizontalScrollBar(), verticalBar);
|
||||
});
|
||||
|
||||
auto zoomChanged = &QmlDesigner::Navigation2dFilter::zoomChanged;
|
||||
connect(filter, zoomChanged, [this](double scale, const QPointF &pos) {
|
||||
applyZoom(m_zoomX + scale, m_zoomY, mapToGlobal(pos.toPoint()));
|
||||
});
|
||||
installEventFilter(filter);
|
||||
viewport()->installEventFilter(filter);
|
||||
|
||||
applyZoom(m_zoomX, m_zoomY);
|
||||
update();
|
||||
|
@@ -31,7 +31,6 @@
|
||||
|
||||
#include <nodeinstanceview.h>
|
||||
#include <designeractionmanager.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <designersettings.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
#include <viewmanager.h>
|
||||
@@ -324,10 +323,6 @@ void Edit3DView::addQuick3DImport()
|
||||
} else {
|
||||
model()->changeImports({import}, {});
|
||||
}
|
||||
|
||||
// Subcomponent manager update needed to make item library entries appear
|
||||
QmlDesignerPlugin::instance()->currentDesignDocument()
|
||||
->updateSubcomponentManagerImport(import);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -177,18 +177,22 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
|
||||
->viewManager().designerActionManager();
|
||||
QHash<QString, QStringList> addedAssets = actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
|
||||
|
||||
// add 3D assets to 3d editor (QtQuick3D import will be added if missing)
|
||||
ItemLibraryInfo *itemLibInfo = m_view->model()->metaInfo().itemLibraryInfo();
|
||||
view()->executeInTransaction("Edit3DWidget::dropEvent", [&] {
|
||||
// add 3D assets to 3d editor (QtQuick3D import will be added if missing)
|
||||
ItemLibraryInfo *itemLibInfo = m_view->model()->metaInfo().itemLibraryInfo();
|
||||
|
||||
const QStringList added3DAssets = addedAssets.value(ComponentCoreConstants::add3DAssetsDisplayString);
|
||||
for (const QString &assetPath : added3DAssets) {
|
||||
QString fileName = QFileInfo(assetPath).baseName();
|
||||
fileName = fileName.at(0).toUpper() + fileName.mid(1); // capitalize first letter
|
||||
QString type = QString("Quick3DAssets.%1.%1").arg(fileName);
|
||||
QList<ItemLibraryEntry> entriesForType = itemLibInfo->entriesForType(type.toLatin1());
|
||||
if (!entriesForType.isEmpty()) // should always be true, but just in case
|
||||
QmlVisualNode::createQml3DNode(view(), entriesForType.at(0), m_canvas->activeScene()).modelNode();
|
||||
}
|
||||
const QStringList added3DAssets = addedAssets.value(ComponentCoreConstants::add3DAssetsDisplayString);
|
||||
for (const QString &assetPath : added3DAssets) {
|
||||
QString fileName = QFileInfo(assetPath).baseName();
|
||||
fileName = fileName.at(0).toUpper() + fileName.mid(1); // capitalize first letter
|
||||
QString type = QString("Quick3DAssets.%1.%1").arg(fileName);
|
||||
QList<ItemLibraryEntry> entriesForType = itemLibInfo->entriesForType(type.toLatin1());
|
||||
if (!entriesForType.isEmpty()) { // should always be true, but just in case
|
||||
QmlVisualNode::createQml3DNode(view(), entriesForType.at(0),
|
||||
m_canvas->activeScene(), {}, false).modelNode();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -62,28 +62,12 @@ FormEditorGraphicsView::FormEditorGraphicsView(QWidget *parent)
|
||||
// eventFilter method so it works also for the space scrolling case as expected
|
||||
QCoreApplication::instance()->installEventFilter(this);
|
||||
|
||||
QmlDesigner::Navigation2dFilter *filter = new QmlDesigner::Navigation2dFilter(this);
|
||||
QmlDesigner::Navigation2dFilter *filter = new QmlDesigner::Navigation2dFilter(viewport());
|
||||
connect(filter, &Navigation2dFilter::zoomIn, this, &FormEditorGraphicsView::zoomIn);
|
||||
connect(filter, &Navigation2dFilter::zoomOut, this, &FormEditorGraphicsView::zoomOut);
|
||||
|
||||
auto panChanged = &Navigation2dFilter::panChanged;
|
||||
connect(filter, panChanged, [this](const QPointF &direction) {
|
||||
QScrollBar *sbx = horizontalScrollBar();
|
||||
QScrollBar *sby = verticalScrollBar();
|
||||
|
||||
// max - min + pageStep = sceneRect.size * scale
|
||||
QPointF min(sbx->minimum(), sby->minimum());
|
||||
QPointF max(sbx->maximum(), sby->maximum());
|
||||
QPointF step(sbx->pageStep(), sby->pageStep());
|
||||
|
||||
QPointF d1 = max - min;
|
||||
QPointF d2 = d1 + step;
|
||||
|
||||
QPoint val = QPointF((direction.x() / d2.x()) * d1.x(), (direction.y() / d2.y()) * d1.y())
|
||||
.toPoint();
|
||||
|
||||
sbx->setValue(sbx->value() - val.x());
|
||||
sby->setValue(sby->value() - val.y());
|
||||
connect(filter, &Navigation2dFilter::panChanged, [this](const QPointF &direction) {
|
||||
Navigation2dFilter::scroll(direction, horizontalScrollBar(), verticalScrollBar());
|
||||
});
|
||||
|
||||
auto zoomChanged = &Navigation2dFilter::zoomChanged;
|
||||
@@ -93,7 +77,7 @@ FormEditorGraphicsView::FormEditorGraphicsView(QWidget *parent)
|
||||
emit this->zoomChanged(transform().m11());
|
||||
}
|
||||
});
|
||||
installEventFilter(filter);
|
||||
viewport()->installEventFilter(filter);
|
||||
}
|
||||
|
||||
bool FormEditorGraphicsView::eventFilter(QObject *watched, QEvent *event)
|
||||
@@ -123,8 +107,8 @@ void FormEditorGraphicsView::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (event->modifiers().testFlag(Qt::ControlModifier))
|
||||
event->ignore();
|
||||
else if (event->source() == Qt::MouseEventNotSynthesized)
|
||||
QGraphicsView::wheelEvent(event);
|
||||
|
||||
QGraphicsView::wheelEvent(event);
|
||||
}
|
||||
|
||||
void FormEditorGraphicsView::mousePressEvent(QMouseEvent *event)
|
||||
|
@@ -599,20 +599,24 @@ void FormEditorWidget::dropEvent(QDropEvent *dropEvent)
|
||||
->viewManager().designerActionManager();
|
||||
QHash<QString, QStringList> addedAssets = actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
|
||||
|
||||
// Create Image components for added image assets
|
||||
const QStringList addedImages = addedAssets.value(ComponentCoreConstants::addImagesDisplayString);
|
||||
for (const QString &imgPath : addedImages) {
|
||||
QmlItemNode::createQmlItemNodeFromImage(m_formEditorView, imgPath, {},
|
||||
m_formEditorView->scene()->rootFormEditorItem()->qmlItemNode());
|
||||
}
|
||||
m_formEditorView->executeInTransaction("FormEditorWidget::dropEvent", [&] {
|
||||
// Create Image components for added image assets
|
||||
const QStringList addedImages = addedAssets.value(ComponentCoreConstants::addImagesDisplayString);
|
||||
for (const QString &imgPath : addedImages) {
|
||||
QmlItemNode::createQmlItemNodeFromImage(m_formEditorView, imgPath, {},
|
||||
m_formEditorView->scene()->rootFormEditorItem()->qmlItemNode(),
|
||||
false);
|
||||
}
|
||||
|
||||
// Create Text components for added font assets
|
||||
const QStringList addedFonts = addedAssets.value(ComponentCoreConstants::addFontsDisplayString);
|
||||
for (const QString &fontPath : addedFonts) {
|
||||
QString fontFamily = QFileInfo(fontPath).baseName();
|
||||
QmlItemNode::createQmlItemNodeFromFont(m_formEditorView, fontFamily, rootItemRect().center(),
|
||||
m_formEditorView->scene()->rootFormEditorItem()->qmlItemNode());
|
||||
}
|
||||
// Create Text components for added font assets
|
||||
const QStringList addedFonts = addedAssets.value(ComponentCoreConstants::addFontsDisplayString);
|
||||
for (const QString &fontPath : addedFonts) {
|
||||
QString fontFamily = QFileInfo(fontPath).baseName();
|
||||
QmlItemNode::createQmlItemNodeFromFont(m_formEditorView, fontFamily, rootItemRect().center(),
|
||||
m_formEditorView->scene()->rootFormEditorItem()->qmlItemNode(),
|
||||
false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -388,9 +388,9 @@ void DesignDocument::updateSubcomponentManager()
|
||||
currentModel()->imports() + currentModel()->possibleImports());
|
||||
}
|
||||
|
||||
void DesignDocument::updateSubcomponentManagerImport(const Import &import)
|
||||
void DesignDocument::addSubcomponentManagerImport(const Import &import)
|
||||
{
|
||||
m_subComponentManager->updateImport(import);
|
||||
m_subComponentManager->addAndParseImport(import);
|
||||
}
|
||||
|
||||
void DesignDocument::deleteSelected()
|
||||
|
@@ -69,7 +69,7 @@ public:
|
||||
void attachRewriterToModel();
|
||||
void close();
|
||||
void updateSubcomponentManager();
|
||||
void updateSubcomponentManagerImport(const Import &import);
|
||||
void addSubcomponentManagerImport(const Import &import);
|
||||
|
||||
bool isUndoAvailable() const;
|
||||
bool isRedoAvailable() const;
|
||||
|
@@ -686,8 +686,6 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
|
||||
|
||||
model->changeImports(newImportsToAdd, {});
|
||||
transaction.commit();
|
||||
for (const Import &import : qAsConst(newImportsToAdd))
|
||||
doc->updateSubcomponentManagerImport(import);
|
||||
}
|
||||
} catch (const RewritingException &e) {
|
||||
addError(tr("Failed to update imports: %1").arg(e.description()));
|
||||
|
@@ -132,6 +132,10 @@ void ItemLibraryView::modelAboutToBeDetached(Model *model)
|
||||
|
||||
void ItemLibraryView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
|
||||
{
|
||||
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
for (const auto &import : addedImports)
|
||||
document->addSubcomponentManagerImport(import);
|
||||
|
||||
updateImports();
|
||||
|
||||
// TODO: generalize the logic below to allow adding/removing any Qml component when its import is added/removed
|
||||
@@ -165,6 +169,10 @@ void ItemLibraryView::importsChanged(const QList<Import> &addedImports, const QL
|
||||
|
||||
void ItemLibraryView::possibleImportsChanged(const QList<Import> &possibleImports)
|
||||
{
|
||||
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
for (const auto &import : possibleImports)
|
||||
document->addSubcomponentManagerImport(import);
|
||||
|
||||
m_widget->updatePossibleImports(possibleImports);
|
||||
}
|
||||
|
||||
|
@@ -357,7 +357,6 @@ void ItemLibraryWidget::handleAddImport(int index)
|
||||
|
||||
auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
document->documentModel()->changeImports({import}, {});
|
||||
document->updateSubcomponentManagerImport(import);
|
||||
|
||||
m_stackedWidget->setCurrentIndex(0); // switch to the Components view after import is added
|
||||
updateSearch();
|
||||
|
@@ -316,7 +316,12 @@ QList<ModelNode> filteredList(const NodeListProperty &property, bool filter, boo
|
||||
|
||||
if (filter) {
|
||||
list.append(Utils::filtered(property.toModelNodeList(), [] (const ModelNode &arg) {
|
||||
return QmlItemNode::isValidQmlItemNode(arg) || NodeHints::fromModelNode(arg).visibleInNavigator();
|
||||
const char auxProp[] = "showInNavigator@Internal";
|
||||
if (arg.hasAuxiliaryData(auxProp))
|
||||
return arg.auxiliaryData(auxProp).toBool();
|
||||
const bool value = QmlItemNode::isValidQmlItemNode(arg) || NodeHints::fromModelNode(arg).visibleInNavigator();
|
||||
arg.setAuxiliaryData(auxProp, value);
|
||||
return value;
|
||||
}));
|
||||
} else {
|
||||
list = property.toModelNodeList();
|
||||
@@ -879,7 +884,6 @@ void NavigatorTreeModel::addImport(const QString &importName)
|
||||
if (possImport.url() == import.url()) {
|
||||
import = possImport;
|
||||
m_view->model()->changeImports({import}, {});
|
||||
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManagerImport(import);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -118,7 +118,7 @@ TimelineWidget::TimelineWidget(TimelineView *view)
|
||||
, m_toolbar(new TimelineToolBar(this))
|
||||
, m_rulerView(new QGraphicsView(this))
|
||||
, m_graphicsView(new QGraphicsView(this))
|
||||
, m_scrollbar(new Navigation2dScrollBar(this))
|
||||
, m_scrollbar(new QScrollBar(this))
|
||||
, m_statusBar(new QLabel(this))
|
||||
, m_timelineView(view)
|
||||
, m_graphicsScene(new TimelineGraphicsScene(this))
|
||||
@@ -160,7 +160,6 @@ TimelineWidget::TimelineWidget(TimelineView *view)
|
||||
m_graphicsView->setFrameShape(QFrame::NoFrame);
|
||||
m_graphicsView->setFrameShadow(QFrame::Plain);
|
||||
m_graphicsView->setLineWidth(0);
|
||||
m_graphicsView->setVerticalScrollBar(new Navigation2dScrollBar);
|
||||
m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
@@ -274,13 +273,19 @@ TimelineWidget::TimelineWidget(TimelineView *view)
|
||||
m_timelineView->addNewTimelineDialog();
|
||||
});
|
||||
|
||||
Navigation2dFilter *filter = new Navigation2dFilter(this, m_scrollbar);
|
||||
connect(filter, &Navigation2dFilter::zoomChanged, [this](double scale, const QPointF& pos) {
|
||||
int s = static_cast<int>(std::round(scale*100.));
|
||||
double ps = m_graphicsScene->mapFromScene(pos.x());
|
||||
m_graphicsScene->setZoom(std::clamp(m_graphicsScene->zoom() + s, 0, 100), ps);
|
||||
Navigation2dFilter *filter = new Navigation2dFilter(m_graphicsView->viewport());
|
||||
connect(filter, &Navigation2dFilter::panChanged, [this](const QPointF &direction) {
|
||||
Navigation2dFilter::scroll(direction, m_scrollbar, m_graphicsView->verticalScrollBar());
|
||||
});
|
||||
installEventFilter(filter);
|
||||
|
||||
connect(filter, &Navigation2dFilter::zoomChanged, [this](double scale, const QPointF &pos) {
|
||||
int s = static_cast<int>(std::round(scale*100.));
|
||||
int scaleFactor = std::clamp(m_graphicsScene->zoom() + s, 0, 100);
|
||||
double ps = m_graphicsScene->mapFromScene(pos.x());
|
||||
m_graphicsScene->setZoom(scaleFactor, ps);
|
||||
m_toolbar->setScaleFactor(scaleFactor);
|
||||
});
|
||||
m_graphicsView->viewport()->installEventFilter(filter);
|
||||
|
||||
m_playbackAnimation->stop();
|
||||
auto playAnimation = [this](QVariant frame) { graphicsScene()->setCurrentFrame(qRound(frame.toDouble())); };
|
||||
|
@@ -40,6 +40,7 @@ QT_FORWARD_DECLARE_CLASS(QShowEvent)
|
||||
QT_FORWARD_DECLARE_CLASS(QString)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
QT_FORWARD_DECLARE_CLASS(QVariantAnimation)
|
||||
QT_FORWARD_DECLARE_CLASS(QScrollBar)
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -97,7 +98,7 @@ private:
|
||||
|
||||
QGraphicsView *m_graphicsView = nullptr;
|
||||
|
||||
Navigation2dScrollBar *m_scrollbar = nullptr;
|
||||
QScrollBar *m_scrollbar = nullptr;
|
||||
|
||||
QLabel *m_statusBar = nullptr;
|
||||
|
||||
|
@@ -90,7 +90,7 @@ TransitionEditorWidget::TransitionEditorWidget(TransitionEditorView *view)
|
||||
, m_toolbar(new TransitionEditorToolBar(this))
|
||||
, m_rulerView(new QGraphicsView(this))
|
||||
, m_graphicsView(new QGraphicsView(this))
|
||||
, m_scrollbar(new Navigation2dScrollBar(this))
|
||||
, m_scrollbar(new QScrollBar(this))
|
||||
, m_statusBar(new QLabel(this))
|
||||
, m_transitionEditorView(view)
|
||||
, m_graphicsScene(new TransitionEditorGraphicsScene(this))
|
||||
@@ -129,7 +129,6 @@ TransitionEditorWidget::TransitionEditorWidget(TransitionEditorView *view)
|
||||
m_graphicsView->setFrameShape(QFrame::NoFrame);
|
||||
m_graphicsView->setFrameShadow(QFrame::Plain);
|
||||
m_graphicsView->setLineWidth(0);
|
||||
m_graphicsView->setVerticalScrollBar(new Navigation2dScrollBar);
|
||||
m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
@@ -223,13 +222,19 @@ TransitionEditorWidget::TransitionEditorWidget(TransitionEditorView *view)
|
||||
m_transitionEditorView->addNewTransition();
|
||||
});
|
||||
|
||||
Navigation2dFilter *filter = new Navigation2dFilter(this, m_scrollbar);
|
||||
connect(filter, &Navigation2dFilter::zoomChanged, [this](double scale, const QPointF& pos) {
|
||||
int s = static_cast<int>(std::round(scale*100.));
|
||||
double ps = m_graphicsScene->mapFromScene(pos.x());
|
||||
m_graphicsScene->setZoom(std::clamp(m_graphicsScene->zoom() + s, 0, 100), ps);
|
||||
Navigation2dFilter *filter = new Navigation2dFilter(m_graphicsView->viewport());
|
||||
connect(filter, &Navigation2dFilter::panChanged, [this](const QPointF &direction) {
|
||||
Navigation2dFilter::scroll(direction, m_scrollbar, m_graphicsView->verticalScrollBar());
|
||||
});
|
||||
installEventFilter(filter);
|
||||
|
||||
connect(filter, &Navigation2dFilter::zoomChanged, [this](double scale, const QPointF &pos) {
|
||||
int s = static_cast<int>(std::round(scale*100.));
|
||||
int scaleFactor = std::clamp(m_graphicsScene->zoom() + s, 0, 100);
|
||||
double ps = m_graphicsScene->mapFromScene(pos.x());
|
||||
m_graphicsScene->setZoom(scaleFactor, ps);
|
||||
m_toolbar->setScaleFactor(scaleFactor);
|
||||
});
|
||||
m_graphicsView->viewport()->installEventFilter(filter);
|
||||
}
|
||||
|
||||
void TransitionEditorWidget::setTransitionActive(bool b)
|
||||
|
@@ -40,6 +40,7 @@ QT_FORWARD_DECLARE_CLASS(QResizeEvent)
|
||||
QT_FORWARD_DECLARE_CLASS(QShowEvent)
|
||||
QT_FORWARD_DECLARE_CLASS(QString)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
QT_FORWARD_DECLARE_CLASS(QScrollBar)
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -47,7 +48,6 @@ class TransitionEditorView;
|
||||
class TransitionEditorToolBar;
|
||||
class TransitionEditorGraphicsScene;
|
||||
class ModelNode;
|
||||
class Navigation2dScrollBar;
|
||||
|
||||
class TransitionEditorWidget : public QWidget
|
||||
{
|
||||
@@ -88,7 +88,7 @@ private:
|
||||
|
||||
QGraphicsView *m_graphicsView = nullptr;
|
||||
|
||||
Navigation2dScrollBar *m_scrollbar = nullptr;
|
||||
QScrollBar *m_scrollbar = nullptr;
|
||||
|
||||
QLabel *m_statusBar = nullptr;
|
||||
|
||||
|
@@ -62,11 +62,14 @@ public:
|
||||
{ return false; }
|
||||
|
||||
private:
|
||||
void handleOriginalTextChanged();
|
||||
|
||||
TextModifier *m_originalModifier;
|
||||
int m_componentStartOffset;
|
||||
int m_componentEndOffset;
|
||||
int m_rootStartOffset;
|
||||
int m_startLength;
|
||||
QString m_originalText;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -101,8 +101,9 @@ public:
|
||||
bool createInTransaction = true);
|
||||
|
||||
static QmlVisualNode createQml3DNode(AbstractView *view,
|
||||
const ItemLibraryEntry &itemLibraryEntry,
|
||||
qint32 sceneRootId = -1, const QVector3D &position = {});
|
||||
const ItemLibraryEntry &itemLibraryEntry,
|
||||
qint32 sceneRootId = -1, const QVector3D &position = {},
|
||||
bool createInTransaction = true);
|
||||
|
||||
static NodeListProperty findSceneNodeProperty(AbstractView *view, qint32 sceneRootId);
|
||||
|
||||
|
@@ -49,7 +49,7 @@ public:
|
||||
explicit SubComponentManager(Model *model, QObject *parent = nullptr);
|
||||
|
||||
void update(const QUrl &fileUrl, const QList<Import> &imports);
|
||||
void updateImport(const Import &import);
|
||||
void addAndParseImport(const Import &import);
|
||||
|
||||
QStringList qmlFiles() const;
|
||||
QStringList directories() const;
|
||||
@@ -59,7 +59,7 @@ private: // functions
|
||||
void parseFile(const QString &canonicalFilePath, bool addToLibrary, const QString&);
|
||||
void parseFile(const QString &canonicalFilePath);
|
||||
|
||||
void addImport(const Import &import, int index = -1);
|
||||
bool addImport(const Import &import, int index = -1);
|
||||
void removeImport(int index);
|
||||
void parseDirectories();
|
||||
QFileInfoList watchedFiles(const QString &canonicalDirPath);
|
||||
|
@@ -69,16 +69,18 @@ SubComponentManager::SubComponentManager(Model *model, QObject *parent)
|
||||
this, [this](const QString &path) { parseDirectory(path); });
|
||||
}
|
||||
|
||||
void SubComponentManager::addImport(const Import &import, int index)
|
||||
bool SubComponentManager::addImport(const Import &import, int index)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << index << import.file().toUtf8();
|
||||
|
||||
bool importExists = false;
|
||||
if (import.isFileImport()) {
|
||||
QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.file()).toLocalFile());
|
||||
if (dirInfo.exists() && dirInfo.isDir()) {
|
||||
const QString canonicalDirPath = dirInfo.canonicalFilePath();
|
||||
m_watcher.addPath(canonicalDirPath);
|
||||
importExists = true;
|
||||
//m_dirToQualifier.insertMulti(canonicalDirPath, import.qualifier()); ### todo: proper support for import as
|
||||
}
|
||||
} else {
|
||||
@@ -91,16 +93,21 @@ void SubComponentManager::addImport(const Import &import, int index)
|
||||
if (dirInfo.exists() && dirInfo.isDir()) {
|
||||
const QString canonicalDirPath = dirInfo.canonicalFilePath();
|
||||
m_watcher.addPath(canonicalDirPath);
|
||||
importExists = true;
|
||||
//m_dirToQualifier.insertMulti(canonicalDirPath, import.qualifier()); ### todo: proper support for import as
|
||||
}
|
||||
}
|
||||
// TODO: QDeclarativeDomImport::Library
|
||||
}
|
||||
|
||||
if (index == -1)
|
||||
m_imports.append(import);
|
||||
else
|
||||
m_imports.insert(index, import);
|
||||
if (importExists) {
|
||||
if (index == -1)
|
||||
m_imports.append(import);
|
||||
else
|
||||
m_imports.insert(index, import);
|
||||
}
|
||||
|
||||
return importExists;
|
||||
}
|
||||
|
||||
void SubComponentManager::removeImport(int index)
|
||||
@@ -544,9 +551,15 @@ void SubComponentManager::update(const QUrl &filePath, const QList<Import> &impo
|
||||
parseDirectories();
|
||||
}
|
||||
|
||||
void SubComponentManager::updateImport(const Import &import)
|
||||
void SubComponentManager::addAndParseImport(const Import &import)
|
||||
{
|
||||
addImport(import);
|
||||
for (const auto &existingImport : std::as_const(m_imports)) {
|
||||
if (import == existingImport)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addImport(import))
|
||||
return;
|
||||
|
||||
if (import.isFileImport()) {
|
||||
QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.file()).toLocalFile());
|
||||
|
@@ -33,10 +33,13 @@ ComponentTextModifier::ComponentTextModifier(TextModifier *originalModifier, int
|
||||
m_componentEndOffset(componentEndOffset),
|
||||
m_rootStartOffset(rootStartOffset)
|
||||
{
|
||||
connect(m_originalModifier, &TextModifier::textChanged, this, &TextModifier::textChanged);
|
||||
connect(m_originalModifier, &TextModifier::textChanged,
|
||||
this, &ComponentTextModifier::handleOriginalTextChanged);
|
||||
|
||||
connect(m_originalModifier, &TextModifier::replaced, this, &TextModifier::replaced);
|
||||
connect(m_originalModifier, &TextModifier::moved, this, &TextModifier::moved);
|
||||
|
||||
m_originalText = m_originalModifier->text();
|
||||
}
|
||||
|
||||
ComponentTextModifier::~ComponentTextModifier() = default;
|
||||
@@ -146,3 +149,45 @@ void ComponentTextModifier::reactivateChangeSignals()
|
||||
{
|
||||
m_originalModifier->reactivateChangeSignals();
|
||||
}
|
||||
|
||||
void ComponentTextModifier::handleOriginalTextChanged()
|
||||
{
|
||||
// Update offsets when original text changes, if necessary
|
||||
|
||||
// Detect and adjust for removal/addition of unrelated text before the subcomponent code,
|
||||
// as that can happen even without user editing the text (e.g. whitespace removal at save time)
|
||||
|
||||
const QString currentText = m_originalModifier->text();
|
||||
|
||||
if (m_originalText.left(m_componentStartOffset) != currentText.left(m_componentStartOffset)) {
|
||||
// Subcomponent item id is the only reliable indicator for adjustment
|
||||
const int idIndex = m_originalText.indexOf("id:", m_componentStartOffset);
|
||||
if (idIndex != -1 && idIndex < m_componentEndOffset) {
|
||||
int newLineIndex = m_originalText.indexOf('\n', idIndex);
|
||||
if (newLineIndex != -1) {
|
||||
const QString checkLine = m_originalText.mid(idIndex, newLineIndex - idIndex);
|
||||
int lineIndex = currentText.indexOf(checkLine);
|
||||
if (lineIndex != -1) {
|
||||
// Paranoia check - This shouldn't happen except when modifying text manually,
|
||||
// but it's possible something was inserted between id and start
|
||||
// of the component, which would throw off the calculation, so check that
|
||||
// the first line is still correct even with new offset.
|
||||
const int diff = idIndex - lineIndex;
|
||||
newLineIndex = m_originalText.indexOf('\n', m_componentStartOffset);
|
||||
if (newLineIndex != -1) {
|
||||
const QString firstLine = m_originalText.mid(m_componentStartOffset,
|
||||
newLineIndex - m_componentStartOffset);
|
||||
const int newStart = m_componentStartOffset - diff;
|
||||
if (firstLine == currentText.mid(newStart, firstLine.size())) {
|
||||
m_componentEndOffset -= diff;
|
||||
m_componentStartOffset = newStart;
|
||||
m_originalText = currentText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit textChanged();
|
||||
}
|
||||
|
@@ -74,8 +74,13 @@ void ModelToTextMerger::nodeRemoved(const ModelNode &removedNode, const NodeAbst
|
||||
void ModelToTextMerger::propertiesRemoved(const QList<AbstractProperty>& propertyList)
|
||||
{
|
||||
foreach (const AbstractProperty &property, propertyList) {
|
||||
if (isInHierarchy(property) && !property.isDefaultProperty())
|
||||
// Default property that has actual binding/value should be removed
|
||||
if (isInHierarchy(property) && (!property.isDefaultProperty()
|
||||
|| property.isBindingProperty()
|
||||
|| property.isVariantProperty()
|
||||
|| property.isNodeProperty())) {
|
||||
schedule(new RemovePropertyRewriteAction(property));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -174,7 +174,7 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromFont(AbstractView *view,
|
||||
};
|
||||
|
||||
if (executeInTransaction)
|
||||
view->executeInTransaction("QmlItemNode::createQmlItemNodeFromImage", doCreateQmlItemNodeFromFont);
|
||||
view->executeInTransaction("QmlItemNode::createQmlItemNodeFromFont", doCreateQmlItemNodeFromFont);
|
||||
else
|
||||
doCreateQmlItemNodeFromFont();
|
||||
|
||||
|
@@ -365,14 +365,15 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
|
||||
|
||||
QmlVisualNode QmlVisualNode::createQml3DNode(AbstractView *view,
|
||||
const ItemLibraryEntry &itemLibraryEntry,
|
||||
qint32 sceneRootId, const QVector3D &position)
|
||||
qint32 sceneRootId, const QVector3D &position,
|
||||
bool createInTransaction)
|
||||
{
|
||||
NodeAbstractProperty sceneNodeProperty = sceneRootId != -1 ? findSceneNodeProperty(view, sceneRootId)
|
||||
: view->rootModelNode().defaultNodeAbstractProperty();
|
||||
|
||||
QTC_ASSERT(sceneNodeProperty.isValid(), return {});
|
||||
|
||||
return createQmlObjectNode(view, itemLibraryEntry, position, sceneNodeProperty).modelNode();
|
||||
return createQmlObjectNode(view, itemLibraryEntry, position, sceneNodeProperty, createInTransaction).modelNode();
|
||||
}
|
||||
|
||||
NodeListProperty QmlVisualNode::findSceneNodeProperty(AbstractView *view, qint32 sceneRootId)
|
||||
|
@@ -173,14 +173,27 @@ void RewriterView::propertiesAboutToBeRemoved(const QList<AbstractProperty> &pro
|
||||
if (textToModelMerger()->isActive())
|
||||
return;
|
||||
|
||||
for (const AbstractProperty &property : propertyList) {
|
||||
if (!property.isDefaultProperty())
|
||||
continue;
|
||||
|
||||
foreach (const AbstractProperty &property, propertyList) {
|
||||
if (property.isDefaultProperty() && property.isNodeListProperty()) {
|
||||
m_removeDefaultPropertyTransaction = beginRewriterTransaction(QByteArrayLiteral("RewriterView::propertiesAboutToBeRemoved"));
|
||||
if (!m_removeDefaultPropertyTransaction.isValid()) {
|
||||
m_removeDefaultPropertyTransaction = beginRewriterTransaction(
|
||||
QByteArrayLiteral("RewriterView::propertiesAboutToBeRemoved"));
|
||||
}
|
||||
|
||||
foreach (const ModelNode &node, property.toNodeListProperty().toModelNodeList()) {
|
||||
modelToTextMerger()->nodeRemoved(node, property.toNodeAbstractProperty(), AbstractView::NoAdditionalChanges);
|
||||
if (property.isNodeListProperty()) {
|
||||
const auto nodeList = property.toNodeListProperty().toModelNodeList();
|
||||
for (const ModelNode &node : nodeList) {
|
||||
modelToTextMerger()->nodeRemoved(node, property.toNodeAbstractProperty(),
|
||||
AbstractView::NoAdditionalChanges);
|
||||
}
|
||||
} else if (property.isBindingProperty() || property.isVariantProperty()
|
||||
|| property.isNodeProperty()) {
|
||||
// Default property that has actual binding/value should be removed.
|
||||
// We need to do it here in propertiesAboutToBeRemoved, because
|
||||
// type is no longer determinable after property is removed from the model.
|
||||
modelToTextMerger()->propertiesRemoved({property});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -33,7 +33,6 @@
|
||||
#include "generateresource.h"
|
||||
#include "generatecmakelists.h"
|
||||
#include "nodeinstanceview.h"
|
||||
#include "gestures.h"
|
||||
|
||||
#include <metainfo.h>
|
||||
#include <connectionview.h>
|
||||
@@ -232,8 +231,6 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
|
||||
if (QFontDatabase::addApplicationFont(fontPath) < 0)
|
||||
qCWarning(qmldesignerLog) << "Could not add font " << fontPath << "to font database";
|
||||
|
||||
TwoFingerSwipe::registerRecognizer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -461,8 +461,6 @@ Project {
|
||||
"componentcore/findimplementation.h",
|
||||
"componentcore/formatoperation.cpp",
|
||||
"componentcore/formatoperation.h",
|
||||
"componentcore/gestures.cpp",
|
||||
"componentcore/gestures.h",
|
||||
"componentcore/layoutingridlayout.cpp",
|
||||
"componentcore/layoutingridlayout.h",
|
||||
"componentcore/theme.cpp",
|
||||
|
@@ -177,7 +177,7 @@ public:
|
||||
QtOptionsPageWidget();
|
||||
~QtOptionsPageWidget();
|
||||
|
||||
static void linkWithQt();
|
||||
static bool linkWithQt();
|
||||
|
||||
private:
|
||||
void apply() final;
|
||||
@@ -857,7 +857,16 @@ void QtOptionsPageWidget::setupLinkWithQtButton()
|
||||
QString tip;
|
||||
canLinkWithQt(&tip);
|
||||
m_ui.linkWithQtButton->setToolTip(tip);
|
||||
connect(m_ui.linkWithQtButton, &QPushButton::clicked, this, &QtOptionsPage::linkWithQt);
|
||||
connect(m_ui.linkWithQtButton, &QPushButton::clicked, this, [this] {
|
||||
if (linkWithQt()) {
|
||||
QWidget *w = window();
|
||||
// close options dialog
|
||||
if (QDialog *dialog = qobject_cast<QDialog *>(w))
|
||||
dialog->accept();
|
||||
else
|
||||
window()->close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void QtOptionsPageWidget::updateCurrentQtName()
|
||||
@@ -950,7 +959,7 @@ static FilePath defaultQtInstallationPath()
|
||||
return FileUtils::homePath() / "Qt";
|
||||
}
|
||||
|
||||
void QtOptionsPageWidget::linkWithQt()
|
||||
bool QtOptionsPageWidget::linkWithQt()
|
||||
{
|
||||
const QString title = tr("Choose Qt Installation");
|
||||
const QString restartText = tr("The change will take effect after restart.");
|
||||
@@ -1019,8 +1028,9 @@ void QtOptionsPageWidget::linkWithQt()
|
||||
}
|
||||
if (askForRestart) {
|
||||
Core::RestartDialog restartDialog(Core::ICore::dialogParent(), restartText);
|
||||
restartDialog.exec();
|
||||
return restartDialog.exec() == QDialog::Accepted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// QtOptionsPage
|
||||
|
@@ -337,6 +337,7 @@ void CodeAssistantPrivate::displayProposal(IAssistProposal *newProposal, AssistR
|
||||
if (!newProposal->hasItemsToPropose(prefix, reason)) {
|
||||
if (newProposal->isCorrective(m_editorWidget))
|
||||
newProposal->makeCorrection(m_editorWidget);
|
||||
destroyContext();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -417,6 +417,10 @@ bool FontSettings::loadColorScheme(const QString &fileName,
|
||||
foreach (const FormatDescription &desc, descriptions) {
|
||||
const TextStyle id = desc.id();
|
||||
if (!m_scheme.contains(id)) {
|
||||
if (id == C_NAMESPACE && m_scheme.contains(C_TYPE)) {
|
||||
m_scheme.setFormatFor(C_NAMESPACE, m_scheme.formatFor(C_TYPE));
|
||||
continue;
|
||||
}
|
||||
Format format;
|
||||
const Format &descFormat = desc.format();
|
||||
// Default fallback for background and foreground is C_TEXT, which is set through
|
||||
|
@@ -835,7 +835,7 @@ void TextDocument::cleanWhitespace(const QTextCursor &cursor)
|
||||
void TextDocument::cleanWhitespace(QTextCursor &cursor, bool inEntireDocument,
|
||||
bool cleanIndentation)
|
||||
{
|
||||
const QString fileName(filePath().fileName());
|
||||
const bool removeTrailingWhitespace = d->m_storageSettings.removeTrailingWhitespace(filePath().fileName());
|
||||
|
||||
auto documentLayout = qobject_cast<TextDocumentLayout*>(d->m_document.documentLayout());
|
||||
Q_ASSERT(cursor.visualNavigation() == false);
|
||||
@@ -862,7 +862,7 @@ void TextDocument::cleanWhitespace(QTextCursor &cursor, bool inEntireDocument,
|
||||
foreach (block, blocks) {
|
||||
QString blockText = block.text();
|
||||
|
||||
if (d->m_storageSettings.removeTrailingWhitespace(fileName))
|
||||
if (removeTrailingWhitespace)
|
||||
TabSettings::removeTrailingWhitespace(cursor, block);
|
||||
|
||||
const int indent = indentations[block.blockNumber()];
|
||||
|
@@ -1572,6 +1572,7 @@ void TextEditorWidgetPrivate::slotSelectionChanged()
|
||||
m_selectBlockAnchor = QTextCursor();
|
||||
// Clear any link which might be showing when the selection changes
|
||||
clearLink();
|
||||
setClipboardSelection();
|
||||
}
|
||||
|
||||
void TextEditorWidget::gotoBlockStart()
|
||||
@@ -5244,7 +5245,6 @@ void TextEditorWidget::mouseReleaseEvent(QMouseEvent *e)
|
||||
return;
|
||||
|
||||
QPlainTextEdit::mouseReleaseEvent(e);
|
||||
d->setClipboardSelection();
|
||||
}
|
||||
|
||||
void TextEditorWidget::mouseDoubleClickEvent(QMouseEvent *e)
|
||||
@@ -5259,7 +5259,6 @@ void TextEditorWidget::mouseDoubleClickEvent(QMouseEvent *e)
|
||||
}
|
||||
|
||||
QPlainTextEdit::mouseDoubleClickEvent(e);
|
||||
d->setClipboardSelection();
|
||||
}
|
||||
|
||||
void TextEditorWidgetPrivate::setClipboardSelection()
|
||||
|
@@ -54,6 +54,7 @@ const char *nameForStyle(TextStyle style)
|
||||
case C_NUMBER: return "Number";
|
||||
case C_STRING: return "String";
|
||||
case C_TYPE: return "Type";
|
||||
case C_NAMESPACE: return "Namespace";
|
||||
case C_LOCAL: return "Local";
|
||||
case C_PARAMETER: return "Parameter";
|
||||
case C_GLOBAL: return "Global";
|
||||
@@ -114,6 +115,7 @@ const char *nameForStyle(TextStyle style)
|
||||
case C_DECLARATION: return "Declaration";
|
||||
case C_FUNCTION_DEFINITION: return "FunctionDefinition";
|
||||
case C_OUTPUT_ARGUMENT: return "OutputArgument";
|
||||
case C_STATIC_MEMBER: return "StaticMember";
|
||||
|
||||
case C_LAST_STYLE_SENTINEL: return "LastStyleSentinel";
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@ enum TextStyle : quint8 {
|
||||
C_NUMBER,
|
||||
C_STRING,
|
||||
C_TYPE,
|
||||
C_NAMESPACE,
|
||||
C_LOCAL,
|
||||
C_PARAMETER,
|
||||
C_GLOBAL,
|
||||
@@ -114,6 +115,7 @@ enum TextStyle : quint8 {
|
||||
C_DECLARATION,
|
||||
C_FUNCTION_DEFINITION,
|
||||
C_OUTPUT_ARGUMENT,
|
||||
C_STATIC_MEMBER,
|
||||
|
||||
C_LAST_STYLE_SENTINEL
|
||||
};
|
||||
|
@@ -160,6 +160,8 @@ FormatDescriptions TextEditorSettingsPrivate::initialFormats()
|
||||
tr("Name of a primitive data type."), Qt::darkYellow);
|
||||
formatDescr.emplace_back(C_TYPE, tr("Type"), tr("Name of a type."),
|
||||
Qt::darkMagenta);
|
||||
formatDescr.emplace_back(C_NAMESPACE, tr("Namespace"), tr("Name of a namespace."),
|
||||
Qt::darkGreen);
|
||||
formatDescr.emplace_back(C_LOCAL, tr("Local"),
|
||||
tr("Local variables."), QColor(9, 46, 100));
|
||||
formatDescr.emplace_back(C_PARAMETER, tr("Parameter"),
|
||||
@@ -361,6 +363,10 @@ FormatDescriptions TextEditorSettingsPrivate::initialFormats()
|
||||
tr("Writable arguments of a function call."),
|
||||
outputArgumentFormat,
|
||||
FormatDescription::ShowAllControls);
|
||||
formatDescr.emplace_back(C_STATIC_MEMBER,
|
||||
tr("Static Member"),
|
||||
tr("Names of static fields or member functions."),
|
||||
FormatDescription::ShowAllControls);
|
||||
|
||||
return formatDescr;
|
||||
}
|
||||
|
@@ -36,14 +36,20 @@ struct TextStyles {
|
||||
TextStyle mainStyle;
|
||||
MixinTextStyles mixinStyles;
|
||||
|
||||
static TextStyles mixinStyle(TextStyle main, TextStyle mixin)
|
||||
static TextStyles mixinStyle(TextStyle main, const QList<TextStyle> &mixins)
|
||||
{
|
||||
TextStyles res;
|
||||
res.mainStyle = main;
|
||||
res.mixinStyles.initializeElements();
|
||||
res.mixinStyles.push_back(mixin);
|
||||
for (TextStyle mixin : mixins)
|
||||
res.mixinStyles.push_back(mixin);
|
||||
return res;
|
||||
}
|
||||
|
||||
static TextStyles mixinStyle(TextStyle main, TextStyle mixin)
|
||||
{
|
||||
return mixinStyle(main, QList<TextStyle>{mixin});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace TextEditor
|
||||
|
Submodule src/shared/qbs updated: 966689ab49...38f233502e
@@ -62,6 +62,7 @@ static QString useKindToString(UseKind useKind)
|
||||
switch (useKind) {
|
||||
CASE_STR(Unknown);
|
||||
CASE_STR(TypeUse);
|
||||
CASE_STR(NamespaceUse);
|
||||
CASE_STR(LocalUse);
|
||||
CASE_STR(FieldUse);
|
||||
CASE_STR(EnumerationUse);
|
||||
@@ -72,6 +73,9 @@ static QString useKindToString(UseKind useKind)
|
||||
CASE_STR(FunctionUse);
|
||||
CASE_STR(FunctionDeclarationUse);
|
||||
CASE_STR(PseudoKeywordUse);
|
||||
CASE_STR(StaticFieldUse);
|
||||
CASE_STR(StaticMethodUse);
|
||||
CASE_STR(StaticMethodDeclarationUse);
|
||||
default:
|
||||
QTest::qFail("Unknown UseKind", __FILE__, __LINE__);
|
||||
return QLatin1String("Unknown UseKind");
|
||||
@@ -246,8 +250,8 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
<< _("namespace N {}\n"
|
||||
"using namespace N;\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 11, 1, Highlighting::TypeUse)
|
||||
<< Use(2, 17, 1, Highlighting::TypeUse));
|
||||
<< Use(1, 11, 1, Highlighting::NamespaceUse)
|
||||
<< Use(2, 17, 1, Highlighting::NamespaceUse));
|
||||
|
||||
QTest::newRow("LocalUse")
|
||||
<< _("int f()\n"
|
||||
@@ -361,21 +365,21 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 8, 5, Highlighting::TypeUse)
|
||||
<< Use(3, 16, 3, Highlighting::FieldUse)
|
||||
<< Use(3, 16, 3, Highlighting::StaticFieldUse)
|
||||
<< Use(4, 12, 5, Highlighting::TypeUse)
|
||||
<< Use(6, 9, 5, Highlighting::TypeUse)
|
||||
<< Use(6, 16, 5, Highlighting::FieldUse)
|
||||
<< Use(7, 14, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(11, 5, 5, Highlighting::TypeUse)
|
||||
<< Use(11, 12, 3, Highlighting::FieldUse)
|
||||
<< Use(11, 12, 3, Highlighting::FieldUse) // FIXME: Should be StaticField
|
||||
<< Use(13, 6, 5, Highlighting::TypeUse)
|
||||
<< Use(13, 13, 5, Highlighting::TypeUse)
|
||||
<< Use(13, 20, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(15, 5, 3, Highlighting::FieldUse)
|
||||
<< Use(15, 5, 3, Highlighting::StaticFieldUse)
|
||||
<< Use(16, 5, 5, Highlighting::TypeUse)
|
||||
<< Use(16, 12, 3, Highlighting::FieldUse)
|
||||
<< Use(16, 12, 3, Highlighting::FieldUse) // FIXME: Should be StaticField
|
||||
<< Use(17, 5, 5, Highlighting::FieldUse)
|
||||
<< Use(17, 12, 3, Highlighting::FieldUse));
|
||||
<< Use(17, 12, 3, Highlighting::StaticFieldUse));
|
||||
|
||||
QTest::newRow("VariableHasTheSameNameAsEnumUse")
|
||||
<< _("struct Foo\n"
|
||||
@@ -443,11 +447,11 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 8, 3, Highlighting::TypeUse)
|
||||
<< Use(3, 16, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(3, 16, 3, Highlighting::StaticMethodDeclarationUse)
|
||||
<< Use(6, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(8, 9, 3, Highlighting::LocalUse)
|
||||
<< Use(8, 15, 3, Highlighting::TypeUse)
|
||||
<< Use(8, 20, 3, Highlighting::FunctionUse));
|
||||
<< Use(8, 20, 3, Highlighting::StaticMethodUse));
|
||||
|
||||
QTest::newRow("8902_staticFunctionHighlightingAsMember_functionArgument")
|
||||
<< _("struct Foo\n"
|
||||
@@ -461,11 +465,11 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 8, 3, Highlighting::TypeUse)
|
||||
<< Use(3, 16, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(3, 16, 3, Highlighting::StaticMethodDeclarationUse)
|
||||
<< Use(6, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(6, 14, 3, Highlighting::LocalUse)
|
||||
<< Use(8, 5, 3, Highlighting::TypeUse)
|
||||
<< Use(8, 10, 3, Highlighting::FunctionUse));
|
||||
<< Use(8, 10, 3, Highlighting::StaticMethodUse));
|
||||
|
||||
QTest::newRow("8902_staticFunctionHighlightingAsMember_templateParameter")
|
||||
<< _("struct Foo\n"
|
||||
@@ -480,11 +484,11 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 8, 3, Highlighting::TypeUse)
|
||||
<< Use(3, 16, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(3, 16, 3, Highlighting::StaticMethodDeclarationUse)
|
||||
<< Use(6, 17, 3, Highlighting::TypeUse)
|
||||
<< Use(7, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(9, 5, 3, Highlighting::TypeUse)
|
||||
<< Use(9, 10, 3, Highlighting::FunctionUse));
|
||||
<< Use(9, 10, 3, Highlighting::StaticMethodUse));
|
||||
|
||||
QTest::newRow("staticFunctionHighlightingAsMember_struct")
|
||||
<< _("struct Foo\n"
|
||||
@@ -499,11 +503,11 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 8, 3, Highlighting::TypeUse)
|
||||
<< Use(3, 16, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(3, 16, 3, Highlighting::StaticMethodDeclarationUse)
|
||||
<< Use(6, 8, 3, Highlighting::TypeUse)
|
||||
<< Use(7, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(9, 5, 3, Highlighting::TypeUse)
|
||||
<< Use(9, 10, 3, Highlighting::FunctionUse));
|
||||
<< Use(9, 10, 3, Highlighting::StaticMethodUse));
|
||||
|
||||
QTest::newRow("QTCREATORBUG8890_danglingPointer")
|
||||
<< _("template<class T> class QList {\n"
|
||||
@@ -569,13 +573,13 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
<< Use(1, 17, 1, Highlighting::TypeUse)
|
||||
<< Use(2, 7, 9, Highlighting::TypeUse)
|
||||
<< Use(5, 12, 1, Highlighting::TypeUse)
|
||||
<< Use(5, 15, 8, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(5, 15, 8, Highlighting::StaticMethodDeclarationUse)
|
||||
<< Use(8, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(10, 6, 3, Highlighting::FunctionDeclarationUse);
|
||||
for (int i = 0; i < 250; ++i) {
|
||||
excessiveUses
|
||||
<< Use(12 + i, 5, 9, Highlighting::TypeUse)
|
||||
<< Use(12 + i, 28, 8, Highlighting::FunctionUse);
|
||||
<< Use(12 + i, 28, 8, Highlighting::StaticMethodUse);
|
||||
}
|
||||
QTest::newRow("QTCREATORBUG8974_danglingPointer")
|
||||
<< excessive
|
||||
@@ -710,11 +714,11 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
<< Use(1, 14, 4, Highlighting::FieldUse)
|
||||
<< Use(2, 6, 4, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(4, 8, 4, Highlighting::FieldUse)
|
||||
<< Use(6, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(6, 11, 3, Highlighting::NamespaceUse)
|
||||
<< Use(7, 16, 4, Highlighting::FieldUse)
|
||||
<< Use(8, 8, 4, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(10, 10, 4, Highlighting::FieldUse)
|
||||
<< Use(13, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(13, 11, 3, Highlighting::NamespaceUse)
|
||||
<< Use(15, 27, 4, Highlighting::FieldUse)
|
||||
<< Use(16, 10, 4, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(16, 19, 4, Highlighting::FieldUse)
|
||||
@@ -792,9 +796,9 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
" Foo foo;\n"
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(1, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(2, 7, 3, Highlighting::TypeUse)
|
||||
<< Use(4, 7, 2, Highlighting::TypeUse)
|
||||
<< Use(4, 7, 2, Highlighting::NamespaceUse)
|
||||
<< Use(4, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(5, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(7, 5, 3, Highlighting::TypeUse)
|
||||
@@ -812,10 +816,10 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
"}\n"
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(1, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(2, 7, 3, Highlighting::TypeUse)
|
||||
<< Use(4, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(5, 7, 2, Highlighting::TypeUse)
|
||||
<< Use(4, 11, 3, Highlighting::NamespaceUse)
|
||||
<< Use(5, 7, 2, Highlighting::NamespaceUse)
|
||||
<< Use(5, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(6, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(8, 5, 3, Highlighting::TypeUse)
|
||||
@@ -831,10 +835,10 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
" Foo foo;\n"
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(1, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(2, 7, 3, Highlighting::TypeUse)
|
||||
<< Use(4, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(6, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(6, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(6, 15, 3, Highlighting::TypeUse)
|
||||
<< Use(7, 5, 3, Highlighting::TypeUse)
|
||||
<< Use(7, 9, 3, Highlighting::LocalUse));
|
||||
@@ -849,7 +853,7 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
" Foo foo;\n"
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(1, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(2, 7, 3, Highlighting::TypeUse)
|
||||
<< Use(5, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(7, 9, 3, Highlighting::LocalUse));
|
||||
@@ -866,9 +870,9 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
"}\n"
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(1, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(2, 7, 3, Highlighting::TypeUse)
|
||||
<< Use(4, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(4, 11, 3, Highlighting::NamespaceUse)
|
||||
<< Use(6, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(8, 9, 3, Highlighting::LocalUse));
|
||||
|
||||
@@ -882,7 +886,7 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
" Foo foo;\n"
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(1, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(2, 7, 3, Highlighting::TypeUse)
|
||||
<< Use(4, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(7, 9, 3, Highlighting::LocalUse));
|
||||
@@ -944,14 +948,14 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
"}\n")
|
||||
<< (UseList()
|
||||
<< Use(1, 8, 1, Highlighting::TypeUse)
|
||||
<< Use(2, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(2, 11, 3, Highlighting::NamespaceUse)
|
||||
<< Use(4, 24, 1, Highlighting::TypeUse)
|
||||
<< Use(4, 34, 10, Highlighting::TypeUse)
|
||||
<< Use(6, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(8, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(6, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(8, 11, 3, Highlighting::NamespaceUse)
|
||||
<< Use(8, 16, 10, Highlighting::TypeUse)
|
||||
<< Use(10, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(12, 5, 2, Highlighting::TypeUse)
|
||||
<< Use(12, 5, 2, Highlighting::NamespaceUse)
|
||||
<< Use(12, 9, 10, Highlighting::TypeUse)
|
||||
<< Use(12, 20, 1, Highlighting::TypeUse)
|
||||
<< Use(12, 23, 1, Highlighting::LocalUse));
|
||||
@@ -967,9 +971,9 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
" Foo foo;\n"
|
||||
"}\n")
|
||||
<< (QList<Use>()
|
||||
<< Use(3, 15, 2, Highlighting::TypeUse)
|
||||
<< Use(3, 15, 2, Highlighting::NamespaceUse)
|
||||
<< Use(3, 27, 3, Highlighting::TypeUse)
|
||||
<< Use(4, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(4, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(4, 15, 3, Highlighting::TypeUse)
|
||||
<< Use(6, 6, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(8, 5, 3, Highlighting::TypeUse)
|
||||
@@ -991,12 +995,12 @@ void tst_CheckSymbols::test_checksymbols_data()
|
||||
"}\n"
|
||||
)
|
||||
<< (QList<Use>()
|
||||
<< Use(1, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(3, 15, 2, Highlighting::TypeUse)
|
||||
<< Use(1, 11, 3, Highlighting::NamespaceUse)
|
||||
<< Use(3, 15, 2, Highlighting::NamespaceUse)
|
||||
<< Use(3, 27, 3, Highlighting::TypeUse)
|
||||
<< Use(4, 11, 2, Highlighting::TypeUse)
|
||||
<< Use(4, 11, 2, Highlighting::NamespaceUse)
|
||||
<< Use(4, 15, 3, Highlighting::TypeUse)
|
||||
<< Use(6, 11, 3, Highlighting::TypeUse)
|
||||
<< Use(6, 11, 3, Highlighting::NamespaceUse)
|
||||
<< Use(8, 10, 3, Highlighting::FunctionDeclarationUse)
|
||||
<< Use(10, 13, 3, Highlighting::LocalUse)
|
||||
);
|
||||
|
@@ -121,8 +121,8 @@ void ExternaltoolTest::testRead1()
|
||||
QCOMPARE(tool->displayCategory(), QString::fromLatin1("Linguist"));
|
||||
QCOMPARE(tool->order(), 1);
|
||||
QCOMPARE(tool->executables().size(), 2);
|
||||
QCOMPARE(tool->executables().at(0), QString::fromLatin1("%{QT_INSTALL_BINS}/lupdate"));
|
||||
QCOMPARE(tool->executables().at(1), QString::fromLatin1("lupdate"));
|
||||
QCOMPARE(tool->executables().at(0), FilePath::fromString("%{QT_INSTALL_BINS}/lupdate"));
|
||||
QCOMPARE(tool->executables().at(1), FilePath::fromString("lupdate"));
|
||||
QCOMPARE(tool->arguments(), QString::fromLatin1("%{CurrentProjectFilePath}"));
|
||||
QCOMPARE(tool->input(), QString());
|
||||
QCOMPARE(tool->workingDirectory(), FilePath::fromString("%{CurrentProjectPath}"));
|
||||
@@ -143,7 +143,7 @@ void ExternaltoolTest::testRead2()
|
||||
QCOMPARE(tool->displayCategory(), QString::fromLatin1("Text"));
|
||||
QCOMPARE(tool->order(), -1);
|
||||
QCOMPARE(tool->executables().size(), 1);
|
||||
QCOMPARE(tool->executables().at(0), QString::fromLatin1("sort"));
|
||||
QCOMPARE(tool->executables().at(0), FilePath::fromString("sort"));
|
||||
QCOMPARE(tool->arguments(), QString());
|
||||
QCOMPARE(tool->input(), QString::fromLatin1("%{CurrentSelection}"));
|
||||
QCOMPARE(tool->workingDirectory(), FilePath::fromString("%{CurrentPath}"));
|
||||
@@ -164,7 +164,7 @@ void ExternaltoolTest::testRead3()
|
||||
QCOMPARE(tool->displayCategory(), QString::fromLatin1("Text"));
|
||||
QCOMPARE(tool->order(), -1);
|
||||
QCOMPARE(tool->executables().size(), 1);
|
||||
QCOMPARE(tool->executables().at(0), QString::fromLatin1("xterm"));
|
||||
QCOMPARE(tool->executables().at(0), FilePath::fromString("xterm"));
|
||||
QVERIFY(tool->arguments().startsWith(QLatin1String("-geom %{")));
|
||||
QCOMPARE(tool->input(), QString());
|
||||
QCOMPARE(tool->workingDirectory(), FilePath::fromString("%{CurrentPath}"));
|
||||
|
@@ -214,7 +214,7 @@ def verifyBuildAndRun():
|
||||
appOutput = logApplicationOutput()
|
||||
if appOutput:
|
||||
test.verify((re.search(".* exited with code \d+", str(appOutput)) or
|
||||
re.search("The program has unexpectedly finished\.", str(appOutput))) and
|
||||
re.search(".* crashed\.", str(appOutput))) and
|
||||
re.search('[Ss]tarting.*', str(appOutput)),
|
||||
"Verifying if built app started and closed successfully.")
|
||||
|
||||
|
@@ -190,22 +190,19 @@ def invokeMenuItem(menu, item, *subItems):
|
||||
itemObject = waitForObjectItem(objectMap.realName(menuObject), item)
|
||||
waitFor("itemObject.enabled", 2000)
|
||||
activateItem(itemObject)
|
||||
numberedPrefix = "(&\\d \| )?"
|
||||
numberedPrefix = "%d | "
|
||||
for subItem in subItems:
|
||||
# we might have numbered sub items (e.g. "Recent Files") - these have this special prefix
|
||||
if subItem.startswith(numberedPrefix):
|
||||
# TODO: Find fix for Qt 6
|
||||
actions = sub.actions()
|
||||
triggered = False
|
||||
for i in range(actions.count()):
|
||||
current = actions.at(i)
|
||||
nonPrefix = subItem[len(numberedPrefix):]
|
||||
matcher = re.match("%s(.*)" % numberedPrefix, str(current.text))
|
||||
if matcher and matcher.group(2) == nonPrefix:
|
||||
itemObject = current
|
||||
for i in range(1, 10):
|
||||
try:
|
||||
itemObject = waitForObjectItem(itemObject, subItem % i, 1000)
|
||||
activateItem(itemObject)
|
||||
triggered = True
|
||||
break
|
||||
except:
|
||||
continue
|
||||
if not triggered:
|
||||
test.fail("Could not trigger '%s' - item missing or code wrong?" % subItem,
|
||||
"Function arguments: '%s', '%s', %s" % (menu, item, str(subItems)))
|
||||
|
@@ -199,7 +199,7 @@ def main():
|
||||
recentFile = os.path.join(folder, current)
|
||||
if recentFile.startswith(home) and platform.system() in ('Linux', 'Darwin'):
|
||||
recentFile = recentFile.replace(home, "~", 1)
|
||||
invokeMenuItem("File", "Recent Files", "(&\\d \| )?%s" % recentFile)
|
||||
invokeMenuItem("File", "Recent Files", "%d | " + recentFile)
|
||||
editor = getEditorForFileSuffix(current)
|
||||
display = displayHintForHighlighterDefinition(current, patterns, lPatterns,
|
||||
addedHaskell, addedLiterateHaskell)
|
||||
|
Reference in New Issue
Block a user