diff --git a/.vscode/settings.json b/.vscode/settings.json index 69e164f..8efca01 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,13 +15,20 @@ "text": "-enable-pretty-printing", "ignoreFailures": true } - ] + ], + "visualizerFile": "${workspaceRoot}/.vscode/qt6.natvis", + "args": ["--path", "D:/", "--name", "Java", "-q", "C:/Qt/Qt6.6.3/6.6.3/msvc2019_64", "-t", "2"] + }, + "cmake.environment": { + "PATH": "${env:PATH};replace;" }, "cmake.options.statusBarVisibility": "visible", "cmake.generator": "Ninja", + "C_Cpp.default.cppStandard": "c++20", + "C_Cpp.default.cStandard": "c11", "C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json", - "C_Cpp.default.cppStandard": "c++17", - "editor.inlayHints.enabled": "off", + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "editor.inlayHints.enabled": "on", "editor.unicodeHighlight.allowedLocales": { "ja": true, "zh-hant": true, @@ -29,6 +36,79 @@ }, "files.associations": { "fstream": "cpp", - "filesystem": "cpp" + "filesystem": "cpp", + "xstring": "cpp", + "algorithm": "cpp", + "array": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "exception": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "list": "cpp", + "locale": "cpp", + "map": "cpp", + "memory": "cpp", + "new": "cpp", + "numeric": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "set": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "utility": "cpp", + "vector": "cpp", + "xfacet": "cpp", + "xhash": "cpp", + "xiosbase": "cpp", + "xlocale": "cpp", + "xlocbuf": "cpp", + "xlocinfo": "cpp", + "xlocmes": "cpp", + "xlocmon": "cpp", + "xlocnum": "cpp", + "xloctime": "cpp", + "xmemory": "cpp", + "xmemory0": "cpp", + "xstddef": "cpp", + "xtr1common": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "format": "cpp", + "atomic": "cpp", + "bit": "cpp", + "charconv": "cpp", + "compare": "cpp", + "concepts": "cpp", + "forward_list": "cpp", + "mutex": "cpp", + "optional": "cpp", + "stop_token": "cpp", + "thread": "cpp" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 1953f20..303f766 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.5) project(codecreate LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) if (MSVC) @@ -17,13 +17,10 @@ endif() message(STATUS "System: ${CMAKE_SYSTEM_NAME}") message(STATUS "Compiler CXX ID: ${CMAKE_CXX_COMPILER_ID}") -set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) - include_directories(3rd) set(PROJECT_SOURCES - main.cpp + main.cpp src/pub.cpp src/pub.h ) add_executable(codecreate ${PROJECT_SOURCES}) diff --git a/main.cpp b/main.cpp index 27e78e2..3608195 100644 --- a/main.cpp +++ b/main.cpp @@ -1,26 +1,48 @@ +#include "src/pub.h" #include <CLI11.hpp> -#include <iostream> -#include <string> #include <filesystem> +#include <format> +#include <fstream> +#include <iostream> +#include <list> +#include <string> #define CODECREATE_VERSION "1.0.0" +enum ProjectType { TYPE_CONSOLE = 0, TYPE_QT_CONSOLE, TYPE_QT_WIDGET }; + struct MParam { + std::string point_code{}; + std::string qt_path{}; + std::string exe_dir{}; std::string des_path{}; + std::string des_dir{}; + std::string name{}; + std::string shortkey{}; + ProjectType type{TYPE_CONSOLE}; }; -namespace fs = std::filesystem; +MParam gParam; +namespace fs = std::filesystem; bool parse_cmd(int argc, char** argv, MParam& param) { std::string intro(""); intro.append(CODECREATE_VERSION); CLI::App app(intro); - app.add_option("-p,--path", param.des_path, "创建工程的位置"); + std::string type; + + app.add_option("-p,--path", param.des_path, "project position"); + app.add_option("-n,--name", param.name, "project name"); + app.add_option("-t,--type", type, "0-console,1-qtconsole,2-qtdialog"); + app.add_option("-q,--qt", param.qt_path, "qt path, bin dir's parent dir."); + app.add_option("-k,--key", param.shortkey, "if not empty, set f5 and alt+g."); try { CLI11_PARSE(app, argc, argv); + param.type = static_cast<ProjectType>(std::stoi(type)); + param.qt_path = CUtil::replace(param.qt_path, "\\", "/"); return true; } catch (const CLI::ParseError& e) { std::cerr << "Error parsing command line: " << e.what() << std::endl; @@ -28,13 +50,389 @@ bool parse_cmd(int argc, char** argv, MParam& param) } } +bool copy_dir(const std::string& source_dir, const std::string& des_dir, bool add_dir = true) +{ + if (!fs::exists(source_dir) || !fs::exists(des_dir)) { + return false; + } + + auto replaceAll = [](const std::string& str, const std::string& from, const std::string& to) { + std::string tp(str); + if (from.empty()) { + return str; + } + std::size_t start_pos = 0; + while ((start_pos = tp.find(from, start_pos)) != std::string::npos) { + tp.replace(start_pos, from.length(), to); + start_pos += to.length(); + } + return tp; + }; + + fs::path des_parent_dir; + if (add_dir) { + des_parent_dir = fs::path(des_dir).append(fs::path(source_dir).filename().string()); + if (!fs::exists(des_parent_dir)) { + fs::create_directories(des_parent_dir); + } + } else { + des_parent_dir = fs::path(des_dir); + } + + std::list<fs::path> paths{}; + for (const auto& entry : fs::directory_iterator(source_dir)) { + paths.push_back(entry); + } + + while (!paths.empty()) { + fs::path path = paths.front(); + paths.pop_front(); + + fs::path destination(replaceAll(path.string(), source_dir, des_parent_dir.string())); + if (fs::is_directory(path)) { + if (!fs::exists(destination)) { + fs::create_directories(destination); + } + for (const auto& entry : fs::directory_iterator(path)) { + paths.push_back(entry); + } + continue; + } + fs::copy_file(path, destination, fs::copy_options::overwrite_existing); + } + return true; +} + +bool create_base() +{ + if (gParam.name.empty()) { + std::cout << std::format("project name is empty.") << std::endl; + return false; + } + + if (!fs::exists(gParam.des_path)) { + std::cout << std::format("{} is not exit.", gParam.des_path) << std::endl; + return false; + } + + fs::path des_dir(gParam.des_path); + gParam.des_dir = des_dir.append(gParam.name).string(); + + if (fs::exists(des_dir)) { + std::cout << std::format("{} is already exist.", des_dir.string()) << "\n"; + return false; + } + + if (!fs::create_directory(des_dir)) { + std::cout << std::format("{} create failed.", des_dir.string()) << std::endl; + return false; + } else { + std::cout << std::format("{} create success.", des_dir.string()) << std::endl; + } + + fs::path point_code_dir(des_dir); + gParam.point_code = point_code_dir.append(".vscode").string(); + + if (!fs::exists(point_code_dir)) { + if (fs::create_directory(point_code_dir)) { + std::cout << std::format("{} create success.", point_code_dir.string()) << std::endl; + } else { + std::cout << std::format("{} create failed.", point_code_dir.string()) << std::endl; + return false; + } + } + + fs::path settings_file(point_code_dir); + fs::path clang_file(des_dir); + settings_file.append("settings.json"); + clang_file.append(".clang-format"); + + fs::path source_settings(gParam.exe_dir); + fs::path clang_format(gParam.exe_dir); + source_settings.append(".vscode").append("settings.json"); + clang_format.append("template").append(".clang-format"); + + std::cout << std::format("source settings is: {}", source_settings.string()) << std::endl; + std::cout << std::format("clang_format is: {}", clang_format.string()) << std::endl; + + if (fs::copy_file(source_settings, settings_file)) { + std::cout << std::format("copy to {} success.", settings_file.string()) << std::endl; + } else { + std::cout << std::format("copy to {} success.", settings_file.string()) << std::endl; + } + + if (fs::copy_file(clang_format, clang_file)) { + std::cout << std::format("copy to {} success.", clang_format.string()) << std::endl; + } else { + std::cout << std::format("copy to {} success.", clang_format.string()) << std::endl; + } + + return true; +} + +bool copy_console() +{ + fs::path console_path(gParam.exe_dir); + console_path.append("template").append("console"); + copy_dir(console_path.string(), gParam.des_dir, false); + + fs::path cmakelist(gParam.des_dir); + cmakelist.append("CMakeLists.txt"); + + std::string str_content; + if (!CUtil::read_txt(cmakelist.string(), str_content)) { + std::cout << std::format("can't open file {}", cmakelist.string()); + return false; + } + + std::string rep("replace"); + std::string ncontent = CUtil::replace(str_content, rep, gParam.name); + + if (!CUtil::save_txt(cmakelist.string(), ncontent)) { + std::cout << std::format("can't write file {}", cmakelist.string()); + return false; + } + + return true; +} + +bool copy_qt_widget() +{ + fs::path widget_path(gParam.exe_dir); + widget_path.append("template").append("qt-widget"); + copy_dir(widget_path.string(), gParam.des_dir, false); + + fs::path cmakelist(gParam.des_dir); + cmakelist.append("CMakeLists.txt"); + + std::string str_content; + if (!CUtil::read_txt(cmakelist.string(), str_content)) { + std::cout << std::format("can't open file {}", cmakelist.string()); + return false; + } + + std::string rep("QT_PATH"); + std::string rep2("untitled3"); + std::string ncontent = CUtil::replace(str_content, rep, gParam.qt_path); + ncontent = CUtil::replace(ncontent, rep2, gParam.name); + + if (!CUtil::save_txt(cmakelist.string(), ncontent)) { + std::cout << std::format("can't write file {}", cmakelist.string()); + return false; + } + + fs::path settings(gParam.point_code); + settings.append("settings.json"); + + std::string settings_content; + if (!CUtil::read_txt(settings.string(), settings_content)) { + std::cout << std::format("can't open file {}", settings.string()); + return false; + } + + std::string from("replace"); + std::string to(gParam.qt_path + "/bin"); + settings_content = CUtil::replace(settings_content, from, to); + + if (!CUtil::save_txt(settings.string(), settings_content)) { + std::cout << std::format("can't write file {}", settings.string()); + return false; + } + + return true; +} + +bool copy_qt_console() +{ + fs::path qt_console_path(gParam.exe_dir); + qt_console_path.append("template").append("qt-console"); + + fs::path cmakelist(qt_console_path); + fs::path main_file(qt_console_path); + cmakelist.append("CMakeLists.txt"); + main_file.append("main.cpp"); + + fs::path save_main(gParam.des_dir); + save_main.append("main.cpp"); + + if (!fs::copy_file(main_file, save_main)) { + std::cout << std::format("can't copy main file {}", main_file.string()); + return false; + } + + std::string str_content; + if (!CUtil::read_txt(cmakelist.string(), str_content)) { + std::cout << std::format("can't open file {}", cmakelist.string()); + return false; + } + + std::string rep("QT_PATH"); + std::string rep2("PROJECT_NAME"); + std::string ncontent = CUtil::replace(str_content, rep, gParam.qt_path); + ncontent = CUtil::replace(ncontent, rep2, gParam.name); + + fs::path save_cmake(gParam.des_dir); + save_cmake.append("CMakeLists.txt"); + + if (!CUtil::save_txt(save_cmake.string(), ncontent)) { + std::cout << std::format("can't write file {}", save_cmake.string()); + return false; + } + + fs::path settings(gParam.point_code); + settings.append("settings.json"); + + std::string settings_content; + if (!CUtil::read_txt(settings.string(), settings_content)) { + std::cout << std::format("can't open file {}", settings.string()); + return false; + } + + std::string from("replace"); + std::string to(gParam.qt_path + "/bin"); + settings_content = CUtil::replace(settings_content, from, to); + + if (!CUtil::save_txt(settings.string(), settings_content)) { + std::cout << std::format("can't write file {}", settings.string()); + return false; + } + + return true; +} + +bool set_key() +{ + std::string shortkey_file = CUtil::get_keybindings_file(); + return true; +} + +bool handle_gdb_qtprinter() +{ +#if _MSC_VER + fs::path template_dir(gParam.exe_dir); + template_dir.append("template"); + + fs::path qt5_file(template_dir); + fs::path qt6_file(template_dir); + qt5_file.append("qt5.natvis"); + qt6_file.append("qt6.natvis"); + + fs::path des_qt5_file(gParam.point_code); + fs::path des_qt6_file(gParam.point_code); + des_qt5_file.append("qt5.natvis"); + des_qt6_file.append("qt6.natvis"); + + if (fs::copy_file(qt5_file, des_qt5_file)) { + std::cout << std::format("copy to {} success.", des_qt5_file.string()) << std::endl; + } else { + std::cout << std::format("copy to {} success.", des_qt5_file.string()) << std::endl; + } + + if (fs::copy_file(qt6_file, des_qt6_file)) { + std::cout << std::format("copy to {} success.", des_qt6_file.string()) << std::endl; + } else { + std::cout << std::format("copy to {} success.", des_qt6_file.string()) << std::endl; + } +#endif + + std::string home = CUtil::get_home(); + if (home.empty()) { + std::cout << "can't get home dir.\n"; + return false; + } + + fs::path gdb_des(home); + gdb_des.append(".gdbinit"); + + fs::path gdb_source(gParam.exe_dir); + gdb_source.append("template").append("qt-printer").append(".gdbinit"); + + if (!fs::exists(gdb_des)) { + if (fs::copy_file(gdb_source, gdb_des)) { + std::cout << std::format("copy to {} success.", gdb_des.string()) << std::endl; + } else { + std::cout << std::format("copy to {} success.", gdb_des.string()) << std::endl; + } + } + + fs::path gdb_path(home); + fs::path gdb_source_path(gParam.exe_dir); + gdb_path.append(".gdb"); + gdb_source_path.append("template").append("qt-printer").append("QtPrinters"); + + if (fs::exists(gdb_path)) { + return true; + } + + fs::create_directory(gdb_path); + + copy_dir(gdb_source_path.string(), gdb_path.string(), true); + + return true; +} + int main(int argc, char** argv) { + std::cout << "\n"; - MParam param; - if (!parse_cmd(argc, argv, param)) { + if (!parse_cmd(argc, argv, gParam)) { return -1; } +#if _DEBUG + std::cout << "Debug Mode." << std::endl; + fs::path exe_path(argv[0]); + gParam.exe_dir = fs::current_path().parent_path().string(); + std::cout << std::format("current_path is: {}", gParam.exe_dir) << "\n"; +#else + std::cout << "Release Mode." << std::endl; + fs::path exe_path(argv[0]); + gParam.exe_dir = fs::current_path().string(); + std::cout << std::format("current_path is: {}", gParam.exe_dir) << "\n"; +#endif + + + // if (!gParam.shortkey.empty()) { + // set_key(); + // return 0; + // } + + switch (gParam.type) { + case TYPE_CONSOLE: { + if (!create_base()) { + return -1; + } + copy_console(); + break; + } + case TYPE_QT_CONSOLE: { + if (gParam.qt_path.empty()) { + std::cout << "qt path is empty.\n"; + break; + } + if (!create_base()) { + return -1; + } + copy_qt_console(); + handle_gdb_qtprinter(); + break; + } + case TYPE_QT_WIDGET: { + if (gParam.qt_path.empty()) { + std::cout << "qt path is empty.\n"; + break; + } + if (!create_base()) { + return -1; + } + copy_qt_widget(); + handle_gdb_qtprinter(); + break; + } + default: + std::cout << std::format("{} is not support.", static_cast<int>(gParam.type)) << "\n"; + break; + } + return 0; } \ No newline at end of file diff --git a/src/pub.cpp b/src/pub.cpp new file mode 100644 index 0000000..89faf1f --- /dev/null +++ b/src/pub.cpp @@ -0,0 +1,84 @@ +#include "pub.h" +#include <filesystem> + +namespace fs = std::filesystem; + +CUtil::CUtil() = default; +CUtil::~CUtil() = default; + +bool CUtil::read_txt(const std::string& path, std::string& content) +{ + std::ifstream file(path); + if (!file.is_open()) { + return false; + } + std::string tp((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>())); + file.close(); + content = std::move(tp); + return true; +} + +bool CUtil::save_txt(const std::string& path, const std::string& content) +{ + std::ofstream file(path, std::ios::out); + if (!file.is_open()) { + return false; + } + file << content; + file.close(); + return true; +} + +std::string CUtil::replace(const std::string& content, const std::string& from, const std::string& to) +{ + std::string tp(content); + if (from.empty()) { + return content; + } + std::size_t start_pos = 0; + while ((start_pos = tp.find(from, start_pos)) != std::string::npos) { + tp.replace(start_pos, from.length(), to); + start_pos += to.length(); + } + return tp; +} + +std::string CUtil::get_home() +{ +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) + char* value = nullptr; + std::size_t len = 0; + auto err = _dupenv_s(&value, &len, "USERPROFILE"); + if (err == 0 && value != nullptr) { + std::string ret(value); + free(value); + return ret; + } + else { + return ""; + } +#else + const char *homedir = getenv("HOME"); + if (homedir) { + return std::string(homedir); + } + return ""; +#endif +} + + +std::string CUtil::get_keybindings_file() +{ + std::string path; + std::string home_dir = get_home(); + fs::path ret(home_dir); +#ifdef _WIN32 + ret.append("AppData/Roaming/Code/User"); +#elif defined(__clang__) && defined(__APPLE__) + ret.append("Library/Application Support/Code/User"); +#else + ret.append(".config/Code/User"); +#endif + path = ret.append("keybindings.json").string(); + return path; +} \ No newline at end of file diff --git a/src/pub.h b/src/pub.h new file mode 100644 index 0000000..03b77eb --- /dev/null +++ b/src/pub.h @@ -0,0 +1,22 @@ +#ifndef PUB_HEADER +#define PUB_HEADER + +#include <string> +#include <fstream> + + +class CUtil +{ +public: + CUtil(); + ~CUtil(); +public: + static bool read_txt(const std::string& path, std::string& content); + static bool save_txt(const std::string& path, const std::string& content); + static std::string replace(const std::string& content, const std::string& from, const std::string& to); + static std::string get_home(); + static std::string get_keybindings_file(); +}; + + +#endif \ No newline at end of file diff --git a/template/.clang-format b/template/.clang-format new file mode 100644 index 0000000..18fbbc4 --- /dev/null +++ b/template/.clang-format @@ -0,0 +1,38 @@ +# .clang-format + +# 风格格式化 +BasedOnStyle: LLVM +# 4 空格缩进 +IndentWidth: 4 +# 连续对齐变量的声明 +AlignConsecutiveDeclarations: true +# 指针左侧对齐 +PointerAlignment: Left +# 访问说明符(public、private等)的偏移 +AccessModifierOffset: -4 +# 大括号 +BreakBeforeBraces: Custom +BraceWrapping: + # 函数定义后面大括号在新行 + AfterFunction: true + # class定义后面 + AfterClass: true + +# 去除C++11的列表初始化的大括号{后和}前的空格 +Cpp11BracedListStyle: true +# 允许重新排版注释 +ReflowComments: true +# 允许排序#include +SortIncludes: true +# 在尾随的评论前添加的空格数(只适用于//) +SpacesBeforeTrailingComments: 3 +# tab宽度 +TabWidth: 4 +# 构造函数的初始化列表要么都在同一行,要么都各自一行 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +# 每行字符的限制,0表示没有限制 +ColumnLimit: 150 +# 允许短的块放在同一行 +AllowShortBlocksOnASingleLine: false +# 是否允许短函数在一行 +AllowShortFunctionsOnASingleLine: InlineOnly \ No newline at end of file diff --git a/template/console/CMakeLists.txt b/template/console/CMakeLists.txt new file mode 100644 index 0000000..5fd021c --- /dev/null +++ b/template/console/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required (VERSION 3.8) +project (replace) +set(CMAKE_CXX_STANDARD 11) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") +endif() +if (MSVC) + add_compile_options(/source-charset:utf-8) + add_compile_options(/EHsc) + add_compile_options(-D_CRT_SECURE_NO_WARNINGS) +endif() + +add_executable(replace main.cpp) diff --git a/template/console/main.cpp b/template/console/main.cpp new file mode 100644 index 0000000..de4e447 --- /dev/null +++ b/template/console/main.cpp @@ -0,0 +1,7 @@ +#include <iostream> + +int main(int argc, char** argv) +{ + std::cout << "..." << std::endl; + return 0; +} diff --git a/template/qt-console/CMakeLists.txt b/template/qt-console/CMakeLists.txt new file mode 100644 index 0000000..befd211 --- /dev/null +++ b/template/qt-console/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.14) + +project(PROJECT_NAME LANGUAGES CXX) +set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} + "QT_PATH" +) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) + +add_executable(PROJECT_NAME + main.cpp +) +target_link_libraries(PROJECT_NAME Qt${QT_VERSION_MAJOR}::Core) + +include(GNUInstallDirs) +install(TARGETS PROJECT_NAME + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/template/qt-console/main.cpp b/template/qt-console/main.cpp new file mode 100644 index 0000000..8e62522 --- /dev/null +++ b/template/qt-console/main.cpp @@ -0,0 +1,8 @@ +#include <QCoreApplication> + +int main(int argc, char* argv[]) +{ + QCoreApplication a(argc, argv); + + return a.exec(); +} diff --git a/template/qt-printer/.gdbinit b/template/qt-printer/.gdbinit new file mode 100644 index 0000000..151a041 --- /dev/null +++ b/template/qt-printer/.gdbinit @@ -0,0 +1,7 @@ +python +import sys, os.path +sys.path.insert(0, os.path.expanduser('~/.gdb/QtPrinters')) +from qt import register_qt_printers +register_qt_printers (gdb.current_objfile()) +end +set print pretty on \ No newline at end of file diff --git a/template/qt-printer/QtPrinters/helper.py b/template/qt-printer/QtPrinters/helper.py new file mode 100644 index 0000000..db9795f --- /dev/null +++ b/template/qt-printer/QtPrinters/helper.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Helper module for pretty-printers + +# SPDX-FileCopyrightText: 2013 Kevin Funk <kfunk@kde.org> +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import sys + +# BEGIN: Utilities for wrapping differences of Python 2.x and Python 3 +# Inspired by http://pythonhosted.org/six/ + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +# create Python 2.x & 3.x compatible iterator base +if PY3: + Iterator = object +else: + class Iterator(object): + + def next(self): + return type(self).__next__(self) +if PY3: + unichr = chr +else: + unichr = unichr + +# END + +# BEGIN: Helper functions for pretty-printers + +def has_field(val, name): + """Check whether @p val (gdb.Value) has a field named @p name""" + try: + val[name] + return True + except Exception: + return False + +def default_iterator(val): + for field in val.type.fields(): + yield field.name, val[field.name] + +class FunctionLookup: + + def __init__(self, gdb, pretty_printers_dict): + self.gdb = gdb + self.pretty_printers_dict = pretty_printers_dict + + def __call__(self, val): + "Look-up and return a pretty-printer that can print val." + + # Get the type. + type = val.type; + + # If it points to a reference, get the reference. + if type.code == self.gdb.TYPE_CODE_REF: + type = type.target () + + # Get the unqualified type, stripped of typedefs. + type = type.unqualified ().strip_typedefs () + + # Get the type name. + typename = type.tag + if typename == None: + return None + + # Iterate over local dictionary of types to determine + # if a printer is registered for that type. Return an + # instantiation of the printer if found. + for function in self.pretty_printers_dict: + if function.search (typename): + return self.pretty_printers_dict[function](val) + + # Cannot find a pretty printer. Return None. + return None + +# END diff --git a/template/qt-printer/QtPrinters/qt.py b/template/qt-printer/QtPrinters/qt.py new file mode 100644 index 0000000..7693192 --- /dev/null +++ b/template/qt-printer/QtPrinters/qt.py @@ -0,0 +1,776 @@ +# -*- coding: iso-8859-1 -*- +# Pretty-printers for Qt 4 and Qt 5. + +# SPDX-FileCopyrightText: 2009 Niko Sams <niko.sams@gmail.com> +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import gdb +import itertools +import re +import time + +from helper import * + +class QStringPrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + ret = "" + + # The QString object may not be initialized yet. In this case 'size' is a bogus value + # or in case of Qt5, 'd' is an invalid pointer and the following lines might throw memory + # access error. Hence the try/catch. + try: + size = self.val['d']['size'] + if size == 0: + return ret + isQt4 = has_field(self.val['d'], 'data') # Qt4 has d->data, Qt5 doesn't. + isQt6 = has_field(self.val['d'], 'ptr') # Qt6 has d->ptr, Qt5 doesn't. + if isQt4: + dataAsCharPointer = self.val['d']['data'].cast(gdb.lookup_type("char").pointer()) + elif isQt6: + dataAsCharPointer = self.val['d']['ptr'].cast(gdb.lookup_type("char").pointer()) + else: + dataAsCharPointer = (self.val['d'] + 1).cast(gdb.lookup_type("char").pointer()) + ret = dataAsCharPointer.string(encoding = 'UTF-16', length = size * 2) + except Exception: + # swallow the exception and return empty string + pass + return ret + + def display_hint (self): + return 'string' + +class QByteArrayPrinter: + + def __init__(self, val): + self.val = val + # Qt4 has 'data', Qt5 doesn't + self.isQt4 = has_field(self.val['d'], 'data') + # Qt6 has d.ptr, Qt5 doesn't + self.isQt6 = has_field(self.val['d'], 'ptr') + + class _iterator(Iterator): + def __init__(self, data, size): + self.data = data + self.size = size + self.count = 0 + + def __iter__(self): + return self + + def __next__(self): + if self.count >= self.size: + raise StopIteration + count = self.count + self.count = self.count + 1 + return ('[%d]' % count, self.data[count]) + + def stringData(self): + if self.isQt4: + return self.val['d']['data'] + elif self.isQt6: + return self.val['d']['ptr'].cast(gdb.lookup_type("char").pointer()) + else: + return self.val['d'].cast(gdb.lookup_type("char").const().pointer()) + self.val['d']['offset'] + + def children(self): + return self._iterator(self.stringData(), self.val['d']['size']) + + def to_string(self): + #todo: handle charset correctly + return self.stringData() + + def display_hint (self): + return 'string' + +class QListPrinter: + "Print a QList" + + class _iterator(Iterator): + def __init__(self, nodetype, d): + self.nodetype = nodetype + self.d = d + self.count = 0 + + #from QTypeInfo::isLarge + isLarge = self.nodetype.sizeof > gdb.lookup_type('void').pointer().sizeof + + isPointer = self.nodetype.code == gdb.TYPE_CODE_PTR + + #unfortunately we can't use QTypeInfo<T>::isStatic as it's all inlined, so use + #this list of types that use Q_DECLARE_TYPEINFO(T, Q_MOVABLE_TYPE) + #(obviously it won't work for custom types) + movableTypes = ['QRect', 'QRectF', 'QString', 'QMargins', 'QLocale', 'QChar', 'QDate', 'QTime', 'QDateTime', 'QVector', + 'QRegExpr', 'QPoint', 'QPointF', 'QByteArray', 'QSize', 'QSizeF', 'QBitArray', 'QLine', 'QLineF', 'QModelIndex', 'QPersitentModelIndex', + 'QVariant', 'QFileInfo', 'QUrl', 'QXmlStreamAttribute', 'QXmlStreamNamespaceDeclaration', 'QXmlStreamNotationDeclaration', + 'QXmlStreamEntityDeclaration', 'QPair<int, int>'] + #this list of types that use Q_DECLARE_TYPEINFO(T, Q_PRIMITIVE_TYPE) (from qglobal.h) + primitiveTypes = ['bool', 'char', 'signed char', 'unsigned char', 'short', 'unsigned short', 'int', 'unsigned int', 'long', 'unsigned long', 'long long', 'unsigned long long', 'float', 'double'] + + if movableTypes.count(self.nodetype.tag) or primitiveTypes.count(str(self.nodetype)): + isStatic = False + else: + isStatic = not isPointer + + self.externalStorage = isLarge or isStatic #see QList::Node::t() + + + def __iter__(self): + return self + + def __next__(self): + isQt6 = has_field(self.d, 'size') + if isQt6: + size = self.d['size'] + else: + size = self.d['end'] - self.d['begin'] + + if self.count >= size: + raise StopIteration + count = self.count + + if isQt6: + value = self.d['ptr'] + count + else: + array = self.d['array'].address + self.d['begin'] + count + if self.externalStorage: + value = array.cast(gdb.lookup_type('QList<%s>::Node' % self.nodetype).pointer())['v'] + else: + value = array + self.count = self.count + 1 + return ('[%d]' % count, value.cast(self.nodetype.pointer()).dereference()) + + def __init__(self, val, container, itype): + self.d = val['d'] + self.container = container + self.isQt6 = has_field(self.d, 'size') + + if self.isQt6: + self.size = self.d['size'] + else: + self.size = self.d['end'] - self.d['begin'] + + if itype == None: + self.itype = val.type.template_argument(0) + else: + self.itype = gdb.lookup_type(itype) + + def children(self): + return self._iterator(self.itype, self.d) + + def to_string(self): + return "%s<%s> (size = %s)" % ( self.container, self.itype, self.size ) + +class QVectorPrinter: + "Print a QVector" + + class _iterator(Iterator): + def __init__(self, nodetype, data, size): + self.nodetype = nodetype + self.data = data + self.size = size + self.count = 0 + + def __iter__(self): + return self + + def __next__(self): + if self.count >= self.size: + raise StopIteration + count = self.count + + self.count = self.count + 1 + return ('[%d]' % count, self.data[count]) + + def __init__(self, val, container): + self.val = val + self.container = container + self.itype = self.val.type.template_argument(0) + + def children(self): + isQt4 = has_field(self.val['d'], 'p') # Qt4 has 'p', Qt5 doesn't + if isQt4: + return self._iterator(self.itype, self.val['p']['array'], self.val['p']['size']) + else: + data = self.val['d'].cast(gdb.lookup_type("char").const().pointer()) + self.val['d']['offset'] + return self._iterator(self.itype, data.cast(self.itype.pointer()), self.val['d']['size']) + + def to_string(self): + size = self.val['d']['size'] + + return "%s<%s> (size = %s)" % ( self.container, self.itype, size ) + +class QLinkedListPrinter: + "Print a QLinkedList" + + class _iterator(Iterator): + def __init__(self, nodetype, begin, size): + self.nodetype = nodetype + self.it = begin + self.pos = 0 + self.size = size + + def __iter__(self): + return self + + def __next__(self): + if self.pos >= self.size: + raise StopIteration + + pos = self.pos + val = self.it['t'] + self.it = self.it['n'] + self.pos = self.pos + 1 + return ('[%d]' % pos, val) + + def __init__(self, val): + self.val = val + self.itype = self.val.type.template_argument(0) + + def children(self): + return self._iterator(self.itype, self.val['e']['n'], self.val['d']['size']) + + def to_string(self): + size = self.val['d']['size'] + + return "QLinkedList<%s> (size = %s)" % ( self.itype, size ) + +class QMapPrinter: + "Print a QMap" + + class _iteratorQt4(Iterator): + def __init__(self, val): + self.val = val + self.ktype = self.val.type.template_argument(0) + self.vtype = self.val.type.template_argument(1) + self.data_node = self.val['e']['forward'][0] + self.count = 0 + + def __iter__(self): + return self + + def payload (self): + if gdb.parse_and_eval: + ret = int(gdb.parse_and_eval('QMap<%s, %s>::payload()' % (self.ktype, self.vtype))) + if (ret): return ret; + + #if the inferior function call didn't work, let's try to calculate ourselves + + #we can't use QMapPayloadNode as it's inlined + #as a workaround take the sum of sizeof(members) + ret = self.ktype.sizeof + ret += self.vtype.sizeof + ret += gdb.lookup_type('void').pointer().sizeof + + #but because of data alignment the value can be higher + #so guess it's aliged by sizeof(void*) + #TODO: find a real solution for this problem + ret += ret % gdb.lookup_type('void').pointer().sizeof + + #for some reason booleans are different + if str(self.vtype) == 'bool': + ret += 2 + + ret -= gdb.lookup_type('void').pointer().sizeof + + return ret + + def concrete (self, data_node): + node_type = gdb.lookup_type('QMapNode<%s, %s>' % (self.ktype, self.vtype)).pointer() + return (data_node.cast(gdb.lookup_type('char').pointer()) - self.payload()).cast(node_type) + + def __next__(self): + if self.data_node == self.val['e']: + raise StopIteration + node = self.concrete(self.data_node).dereference() + if self.count % 2 == 0: + item = node['key'] + else: + item = node['value'] + self.data_node = node['forward'][0] + + result = ('[%d]' % self.count, item) + self.count = self.count + 1 + return result + + class _iteratorQt5: + def __init__(self, val): + realtype = val.type.strip_typedefs() + keytype = realtype.template_argument(0) + valtype = realtype.template_argument(1) + node_type = gdb.lookup_type('QMapData<' + keytype.name + ',' + valtype.name + '>::Node') + self.node_p_type = node_type.pointer() + self.root = val['d']['header'] + self.current = None + self.next_is_key = True + self.i = -1 + # we store the path here to avoid keeping re-fetching + # values from the inferior (also, skips the pointer + # arithmetic involved in using the parent pointer) + self.path = [] + + def __iter__(self): + return self + + def moveToNextNode(self): + if self.current is None: + # find the leftmost node + if not self.root['left']: + return False + self.current = self.root + while self.current['left']: + self.path.append(self.current) + self.current = self.current['left'] + elif self.current['right']: + self.path.append(self.current) + self.current = self.current['right'] + while self.current['left']: + self.path.append(self.current) + self.current = self.current['left'] + else: + last = self.current + self.current = self.path.pop() + while self.current['right'] == last: + last = self.current + self.current = self.path.pop() + # if there are no more parents, we are at the root + if len(self.path) == 0: + return False + return True + + def __next__(self): + if self.next_is_key: + if not self.moveToNextNode(): + raise StopIteration + self.current_typed = self.current.reinterpret_cast(self.node_p_type) + self.next_is_key = False + self.i += 1 + return ('key' + str(self.i), self.current_typed['key']) + else: + self.next_is_key = True + return ('value' + str(self.i), self.current_typed['value']) + + def next(self): + return self.__next__() + + def __init__(self, val, container): + self.val = val + self.container = container + + def children(self): + if self.val['d']['size'] == 0: + return [] + + isQt4 = has_field(self.val, 'e') # Qt4 has 'e', Qt5 doesn't + if isQt4: + return self._iteratorQt4(self.val) + else: + return self._iteratorQt5(self.val) + + def to_string(self): + size = self.val['d']['size'] + + return "%s<%s, %s> (size = %s)" % ( self.container, self.val.type.template_argument(0), self.val.type.template_argument(1), size ) + + def display_hint (self): + return 'map' + +class QHashPrinter: + "Print a QHash" + + class _iterator(Iterator): + def __init__(self, val): + self.val = val + self.d = self.val['d'] + self.ktype = self.val.type.template_argument(0) + self.vtype = self.val.type.template_argument(1) + self.end_node = self.d.cast(gdb.lookup_type('QHashData::Node').pointer()) + self.data_node = self.firstNode() + self.count = 0 + + def __iter__(self): + return self + + def hashNode (self): + "Casts the current QHashData::Node to a QHashNode and returns the result. See also QHash::concrete()" + return self.data_node.cast(gdb.lookup_type('QHashNode<%s, %s>' % (self.ktype, self.vtype)).pointer()) + + def firstNode (self): + "Get the first node, See QHashData::firstNode()." + e = self.d.cast(gdb.lookup_type('QHashData::Node').pointer()) + #print "QHashData::firstNode() e %s" % e + bucketNum = 0 + bucket = self.d['buckets'][bucketNum] + #print "QHashData::firstNode() *bucket %s" % bucket + n = self.d['numBuckets'] + #print "QHashData::firstNode() n %s" % n + while n: + #print "QHashData::firstNode() in while, n %s" % n; + if bucket != e: + #print "QHashData::firstNode() in while, return *bucket %s" % bucket + return bucket + bucketNum += 1 + bucket = self.d['buckets'][bucketNum] + #print "QHashData::firstNode() in while, new bucket %s" % bucket + n -= 1 + #print "QHashData::firstNode() return e %s" % e + return e + + + def nextNode (self, node): + "Get the nextNode after the current, see also QHashData::nextNode()." + #print "******************************** nextNode" + #print "nextNode: node %s" % node + next = node['next'].cast(gdb.lookup_type('QHashData::Node').pointer()) + e = next + + #print "nextNode: next %s" % next + if next['next']: + #print "nextNode: return next" + return next + + #print "nextNode: node->h %s" % node['h'] + #print "nextNode: numBuckets %s" % self.d['numBuckets'] + start = (node['h'] % self.d['numBuckets']) + 1 + bucketNum = start + #print "nextNode: start %s" % start + bucket = self.d['buckets'][start] + #print "nextNode: bucket %s" % bucket + n = self.d['numBuckets'] - start + #print "nextNode: n %s" % n + while n: + #print "nextNode: in while; n %s" % n + #print "nextNode: in while; e %s" % e + #print "nextNode: in while; *bucket %s" % bucket + if bucket != e: + #print "nextNode: in while; return bucket %s" % bucket + return bucket + bucketNum += 1 + bucket = self.d['buckets'][bucketNum] + n -= 1 + #print "nextNode: return e %s" % e + return e + + def __next__(self): + "GDB iteration, first call returns key, second value and then jumps to the next hash node." + if self.data_node == self.end_node: + raise StopIteration + + node = self.hashNode() + + if self.count % 2 == 0: + item = node['key'] + else: + item = node['value'] + self.data_node = self.nextNode(self.data_node) + + self.count = self.count + 1 + return ('[%d]' % self.count, item) + + def __init__(self, val, container): + self.val = val + self.container = container + + def children(self): + return self._iterator(self.val) + + def to_string(self): + size = self.val['d']['size'] + + return "%s<%s, %s> (size = %s)" % ( self.container, self.val.type.template_argument(0), self.val.type.template_argument(1), size ) + + def display_hint (self): + return 'map' + +class QDatePrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + julianDay = self.val['jd'] + + if julianDay == 0: + return "invalid QDate" + + # Copied from Qt sources + if julianDay >= 2299161: + # Gregorian calendar starting from October 15, 1582 + # This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern + ell = julianDay + 68569; + n = (4 * ell) / 146097; + ell = ell - (146097 * n + 3) / 4; + i = (4000 * (ell + 1)) / 1461001; + ell = ell - (1461 * i) / 4 + 31; + j = (80 * ell) / 2447; + d = ell - (2447 * j) / 80; + ell = j / 11; + m = j + 2 - (12 * ell); + y = 100 * (n - 49) + i + ell; + else: + # Julian calendar until October 4, 1582 + # Algorithm from Frequently Asked Questions about Calendars by Claus Toendering + julianDay += 32082; + dd = (4 * julianDay + 3) / 1461; + ee = julianDay - (1461 * dd) / 4; + mm = ((5 * ee) + 2) / 153; + d = ee - (153 * mm + 2) / 5 + 1; + m = mm + 3 - 12 * (mm / 10); + y = dd - 4800 + (mm / 10); + if y <= 0: + --y; + return "%d-%02d-%02d" % (y, m, d) + +class QTimePrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + ds = self.val['mds'] + + if ds == -1: + return "invalid QTime" + + MSECS_PER_HOUR = 3600000 + SECS_PER_MIN = 60 + MSECS_PER_MIN = 60000 + + hour = ds / MSECS_PER_HOUR + minute = (ds % MSECS_PER_HOUR) / MSECS_PER_MIN + second = (ds / 1000)%SECS_PER_MIN + msec = ds % 1000 + return "%02d:%02d:%02d.%03d" % (hour, minute, second, msec) + +class QDateTimePrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + time_t = gdb.parse_and_eval("reinterpret_cast<const QDateTime*>(%s)->toSecsSinceEpoch()" % self.val.address) + return time.ctime(int(time_t)) + +class QUrlPrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + # first try to access the Qt 5 data + try: + int_type = gdb.lookup_type('int') + string_type = gdb.lookup_type('QString') + string_pointer = string_type.pointer() + + addr = self.val['d'].cast(gdb.lookup_type('char').pointer()) + if not addr: + return "<invalid>" + # skip QAtomicInt ref + addr += int_type.sizeof + # handle int port + port = addr.cast(int_type.pointer()).dereference() + addr += int_type.sizeof + # handle QString scheme + scheme = QStringPrinter(addr.cast(string_pointer).dereference()).to_string() + addr += string_type.sizeof + # handle QString username + username = QStringPrinter(addr.cast(string_pointer).dereference()).to_string() + addr += string_type.sizeof + # skip QString password + addr += string_type.sizeof + # handle QString host + host = QStringPrinter(addr.cast(string_pointer).dereference()).to_string() + addr += string_type.sizeof + # handle QString path + path = QStringPrinter(addr.cast(string_pointer).dereference()).to_string() + addr += string_type.sizeof + # handle QString query + query = QStringPrinter(addr.cast(string_pointer).dereference()).to_string() + addr += string_type.sizeof + # handle QString fragment + fragment = QStringPrinter(addr.cast(string_pointer).dereference()).to_string() + + url = "" + if len(scheme) > 0: + # TODO: always adding // is apparently not compliant in all cases + url += scheme + "://" + if len(host) > 0: + if len(username) > 0: + url += username + "@" + url += host + if port != -1: + url += ":" + str(port) + url += path + if len(query) > 0: + url += "?" + query + if len(fragment) > 0: + url += "#" + fragment + + return url + except: + pass + # then try to print directly, but that might lead to issues (see http://sourceware-org.1504.n7.nabble.com/help-Calling-malloc-from-a-Python-pretty-printer-td284031.html) + try: + return gdb.parse_and_eval("reinterpret_cast<const QUrl*>(%s)->toString((QUrl::FormattingOptions)QUrl::PrettyDecoded)" % self.val.address) + except: + pass + # if everything fails, maybe we deal with Qt 4 code + try: + return self.val['d']['encodedOriginal'] + except RuntimeError: + #if no debug information is available for Qt, try guessing the correct address for encodedOriginal + #problem with this is that if QUrlPrivate members get changed, this fails + offset = gdb.lookup_type('int').sizeof + offset += offset % gdb.lookup_type('void').pointer().sizeof #alignment + offset += gdb.lookup_type('QString').sizeof * 6 + offset += gdb.lookup_type('QByteArray').sizeof + encodedOriginal = self.val['d'].cast(gdb.lookup_type('char').pointer()); + encodedOriginal += offset + encodedOriginal = encodedOriginal.cast(gdb.lookup_type('QByteArray').pointer()).dereference(); + encodedOriginal = encodedOriginal['d']['data'].string() + return encodedOriginal + +class QSetPrinter: + "Print a QSet" + + def __init__(self, val): + self.val = val + + class _iterator(Iterator): + def __init__(self, hashIterator): + self.hashIterator = hashIterator + self.count = 0 + + def __iter__(self): + return self + + def __next__(self): + if self.hashIterator.data_node == self.hashIterator.end_node: + raise StopIteration + + node = self.hashIterator.hashNode() + + item = node['key'] + self.hashIterator.data_node = self.hashIterator.nextNode(self.hashIterator.data_node) + + self.count = self.count + 1 + return ('[%d]' % (self.count-1), item) + + def children(self): + hashPrinter = QHashPrinter(self.val['q_hash'], None) + hashIterator = hashPrinter._iterator(self.val['q_hash']) + return self._iterator(hashIterator) + + def to_string(self): + size = self.val['q_hash']['d']['size'] + + return "QSet<%s> (size = %s)" % ( self.val.type.template_argument(0), size ) + + +class QCharPrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + return unichr(self.val['ucs']) + + def display_hint (self): + return 'string' + +class QUuidPrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + return "QUuid({%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x})" % (int(self.val['data1']), int(self.val['data2']), int(self.val['data3']), + int(self.val['data4'][0]), int(self.val['data4'][1]), + int(self.val['data4'][2]), int(self.val['data4'][3]), + int(self.val['data4'][4]), int(self.val['data4'][5]), + int(self.val['data4'][6]), int(self.val['data4'][7])) + + def display_hint (self): + return 'string' + +class QVariantPrinter: + + def __init__(self, val): + self.val = val + + def to_string(self): + d = self.val['d'] + + if d['is_null']: + return "QVariant(NULL)" + + data_type = d['type'] + type_str = ("type = %d" % data_type) + try: + typeAsCharPointer = (gdb.parse_and_eval("QVariant::typeToName(%d)" % data_type).cast(gdb.lookup_type("char").pointer())) + if typeAsCharPointer: + type_str = typeAsCharPointer.string(encoding = 'UTF-8') + except Exception as e: + pass + + data = d['data'] + is_shared = d['is_shared'] + value_str = "" + if is_shared: + private_shared = data['shared'].dereference() + value_str = "PrivateShared(%s)" % hex(private_shared['ptr']) + elif type_str.startswith("type = "): + value_str = str(data['ptr']) + else: + type_obj = None + try: + type_obj = gdb.lookup_type(type_str) + except Exception as e: + value_str = str(data['ptr']) + if type_obj: + if type_obj.sizeof > type_obj.pointer().sizeof: + value_ptr = data['ptr'].reinterpret_cast(type_obj.const().pointer()) + value_str = str(value_ptr.dereference()) + else: + value_ptr = data['c'].address.reinterpret_cast(type_obj.const().pointer()) + value_str = str(value_ptr.dereference()) + + return "QVariant(%s, %s)" % (type_str, value_str) + +pretty_printers_dict = {} + +def register_qt_printers (obj): + if obj == None: + obj = gdb + + obj.pretty_printers.append(FunctionLookup(gdb, pretty_printers_dict)) + +def build_dictionary (): + pretty_printers_dict[re.compile('^QString$')] = lambda val: QStringPrinter(val) + pretty_printers_dict[re.compile('^QByteArray$')] = lambda val: QByteArrayPrinter(val) + pretty_printers_dict[re.compile('^QList<.*>$')] = lambda val: QListPrinter(val, 'QList', None) + pretty_printers_dict[re.compile('^QStringList$')] = lambda val: QListPrinter(val, 'QStringList', 'QString') + pretty_printers_dict[re.compile('^QQueue')] = lambda val: QListPrinter(val, 'QQueue', None) + pretty_printers_dict[re.compile('^QVector<.*>$')] = lambda val: QVectorPrinter(val, 'QVector') + pretty_printers_dict[re.compile('^QStack<.*>$')] = lambda val: QVectorPrinter(val, 'QStack') + pretty_printers_dict[re.compile('^QLinkedList<.*>$')] = lambda val: QLinkedListPrinter(val) + pretty_printers_dict[re.compile('^QMap<.*>$')] = lambda val: QMapPrinter(val, 'QMap') + pretty_printers_dict[re.compile('^QMultiMap<.*>$')] = lambda val: QMapPrinter(val, 'QMultiMap') + pretty_printers_dict[re.compile('^QHash<.*>$')] = lambda val: QHashPrinter(val, 'QHash') + pretty_printers_dict[re.compile('^QMultiHash<.*>$')] = lambda val: QHashPrinter(val, 'QMultiHash') + pretty_printers_dict[re.compile('^QDate$')] = lambda val: QDatePrinter(val) + pretty_printers_dict[re.compile('^QTime$')] = lambda val: QTimePrinter(val) + pretty_printers_dict[re.compile('^QDateTime$')] = lambda val: QDateTimePrinter(val) + pretty_printers_dict[re.compile('^QUrl$')] = lambda val: QUrlPrinter(val) + pretty_printers_dict[re.compile('^QSet<.*>$')] = lambda val: QSetPrinter(val) + pretty_printers_dict[re.compile('^QChar$')] = lambda val: QCharPrinter(val) + pretty_printers_dict[re.compile('^QUuid')] = lambda val: QUuidPrinter(val) + pretty_printers_dict[re.compile('^QVariant')] = lambda val: QVariantPrinter(val) + + +build_dictionary () diff --git a/template/qt-widget/CMakeLists.txt b/template/qt-widget/CMakeLists.txt new file mode 100644 index 0000000..6a4a32a --- /dev/null +++ b/template/qt-widget/CMakeLists.txt @@ -0,0 +1,74 @@ +cmake_minimum_required(VERSION 3.5) + +project(untitled3 VERSION 0.1 LANGUAGES CXX) + +set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} + "QT_PATH" +) + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) + +set(PROJECT_SOURCES + main.cpp + mainwidget.cpp + mainwidget.h + mainwidget.ui +) + +if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) + qt_add_executable(untitled3 + MANUAL_FINALIZATION + ${PROJECT_SOURCES} + ) +# Define target properties for Android with Qt 6 as: +# set_property(TARGET untitled3 APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR +# ${CMAKE_CURRENT_SOURCE_DIR}/android) +# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation +else() + if(ANDROID) + add_library(untitled3 SHARED + ${PROJECT_SOURCES} + ) +# Define properties for Android with Qt 5 after find_package() calls as: +# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") + else() + add_executable(untitled3 + ${PROJECT_SOURCES} + ) + endif() +endif() + +target_link_libraries(untitled3 PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) + +# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. +# If you are developing for iOS or macOS you should consider setting an +# explicit, fixed bundle identifier manually though. +if(${QT_VERSION} VERSION_LESS 6.1.0) + set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.untitled3) +endif() +set_target_properties(untitled3 PROPERTIES + ${BUNDLE_ID_OPTION} + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE +) + +include(GNUInstallDirs) +install(TARGETS untitled3 + BUNDLE DESTINATION . + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +if(QT_VERSION_MAJOR EQUAL 6) + qt_finalize_executable(untitled3) +endif() diff --git a/template/qt-widget/main.cpp b/template/qt-widget/main.cpp new file mode 100644 index 0000000..a0f002b --- /dev/null +++ b/template/qt-widget/main.cpp @@ -0,0 +1,11 @@ +#include "mainwidget.h" + +#include <QApplication> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWidget w; + w.show(); + return a.exec(); +} diff --git a/template/qt-widget/mainwidget.cpp b/template/qt-widget/mainwidget.cpp new file mode 100644 index 0000000..fec3eff --- /dev/null +++ b/template/qt-widget/mainwidget.cpp @@ -0,0 +1,14 @@ +#include "mainwidget.h" +#include "./ui_mainwidget.h" + +MainWidget::MainWidget(QWidget *parent) + : QWidget(parent) + , ui(new Ui::MainWidget) +{ + ui->setupUi(this); +} + +MainWidget::~MainWidget() +{ + delete ui; +} diff --git a/template/qt-widget/mainwidget.h b/template/qt-widget/mainwidget.h new file mode 100644 index 0000000..a186878 --- /dev/null +++ b/template/qt-widget/mainwidget.h @@ -0,0 +1,23 @@ +#ifndef MAINWIDGET_H +#define MAINWIDGET_H + +#include <QWidget> + +QT_BEGIN_NAMESPACE +namespace Ui { +class MainWidget; +} +QT_END_NAMESPACE + +class MainWidget : public QWidget +{ + Q_OBJECT + +public: + MainWidget(QWidget *parent = nullptr); + ~MainWidget(); + +private: + Ui::MainWidget *ui; +}; +#endif // MAINWIDGET_H diff --git a/template/qt-widget/mainwidget.ui b/template/qt-widget/mainwidget.ui new file mode 100644 index 0000000..74273fb --- /dev/null +++ b/template/qt-widget/mainwidget.ui @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWidget</class> + <widget class="QWidget" name="MainWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>600</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWidget</string> + </property> + </widget> + <resources/> + <connections/> +</ui> diff --git a/template/qt5.natvis b/template/qt5.natvis new file mode 100644 index 0000000..7d18567 --- /dev/null +++ b/template/qt5.natvis @@ -0,0 +1,814 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--************************************************************************************************ + Copyright (C) 2023 The Qt Company Ltd. + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +*************************************************************************************************--> + +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + + <Type Name="QUuid"> + <DisplayString>{{{data1,Xb}-{data2,Xb}-{data3,Xb}-{(data4[0]),nvoXb}{(data4[1]),nvoXb}-{(data4[2]),nvoXb}{(data4[3]),nvoXb}{(data4[4]),nvoXb}{(data4[5]),nvoXb}{(data4[6]),nvoXb}{(data4[7]),nvoXb}}}</DisplayString> + </Type> + + <Type Name="QPoint"> + <AlternativeType Name="QPointF"/> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name="QRect"> + <DisplayString>{{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }}</DisplayString> + <Expand> + <Item Name="[x]">x1</Item> + <Item Name="[y]">y1</Item> + <Item Name="[width]">x2 - x1 + 1</Item> + <Item Name="[height]">y2 - y1 + 1</Item> + </Expand> + </Type> + + <Type Name="QRectF"> + <DisplayString>{{ x = {xp}, y = {yp}, width = {w}, height = {h} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[width]">w</Item> + <Item Name="[height]">h</Item> + </Expand> + </Type> + + <Type Name="QSize"> + <AlternativeType Name="QSizeF"/> + <DisplayString>{{ width = {wd}, height = {ht} }}</DisplayString> + <Expand> + <Item Name="[width]">wd</Item> + <Item Name="[height]">ht</Item> + </Expand> + </Type> + + <Type Name="QLine"> + <AlternativeType Name="QLineF"/> + <DisplayString>{{ start point = {pt1}, end point = {pt2} }}</DisplayString> + <Expand> + <Synthetic Name="[start point]"> + <DisplayString>{pt1}</DisplayString> + <Expand> + <ExpandedItem>pt1</ExpandedItem> + </Expand> + </Synthetic> + <Synthetic Name="[end point]"> + <DisplayString>{pt2}</DisplayString> + <Expand> + <ExpandedItem>pt2</ExpandedItem> + </Expand> + </Synthetic> + + </Expand> + </Type> + + <Type Name="QPolygon"> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPoint*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QPolygonF"> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[closed]"> + d->size > 0 + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).xp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).xp) + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).yp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).yp) + </Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPointF*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name ="QVector2D"> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name ="QVector3D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + </Expand> + </Type> + + <Type Name ="QVector4D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + <Item Name="[w]">wp</Item> + </Expand> + </Type> + + <Type Name ="QMatrix"> + <DisplayString> + {{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">_m11</Item> + <Item Name="[m12]">_m12</Item> + <Item Name="[m21]">_m21</Item> + <Item Name="[m22]">_m22</Item> + <Item Name="[dx]">_dx</Item> + <Item Name="[dy]">_dy</Item> + </Expand> + </Type> + + <Type Name ="QMatrix4x4"> + <DisplayString> + {{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">m[0][0]</Item> + <Item Name="[m12]">m[1][0]</Item> + <Item Name="[m13]">m[2][0]</Item> + <Item Name="[m14]">m[3][0]</Item> + <Item Name="[m21]">m[0][1]</Item> + <Item Name="[m22]">m[1][1]</Item> + <Item Name="[m23]">m[2][1]</Item> + <Item Name="[m24]">m[3][1]</Item> + <Item Name="[m31]">m[0][2]</Item> + <Item Name="[m32]">m[1][2]</Item> + <Item Name="[m33]">m[2][2]</Item> + <Item Name="[m34]">m[3][2]</Item> + <Item Name="[m41]">m[0][3]</Item> + <Item Name="[m42]">m[1][3]</Item> + <Item Name="[m43]">m[2][3]</Item> + <Item Name="[m44]">m[3][3]</Item> + </Expand> + </Type> + + <Type Name="QSizePolicy"> + <DisplayString> + {{ horizontal = {static_cast<Policy>(bits.horPolicy)}, vertical = {static_cast<Policy>(bits.verPolicy)}, type = {ControlType(1 << bits.ctype)} }} + </DisplayString> + <Expand> + <Synthetic Name="[vertical policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.verPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[horizontal policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.horPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[control type]"> + <DisplayString>QSizePolicy::ControlType::{ControlType(1 << bits.ctype)}</DisplayString> + </Synthetic> + <Synthetic Name="[expanding directions]"> + <DisplayString + Condition="(static_cast<Policy>(bits.verPolicy) & ExpandFlag)"> + Qt::Vertical (2) + </DisplayString> + <DisplayString + Condition="(static_cast<Policy>(bits.horPolicy) & ExpandFlag)"> + Qt::Horizontal (1) + </DisplayString> + </Synthetic> + <Item Name="[vertical stretch]">static_cast<int>(bits.verStretch)</Item> + <Item Name="[horizontal stretch]">static_cast<int>(bits.horStretch)</Item> + <Item Name="[has height for width]">bits.hfw == 1</Item> + <Item Name="[has width for height]">bits.wfh == 1</Item> + </Expand> + </Type> + + <Type Name="QChar"> + <DisplayString>{ucs,c}</DisplayString> + <StringView>ucs,c</StringView> + <Expand> + <Item Name="[latin 1]">ucs > 0xff ? '\0' : char(ucs),c</Item> + <Item Name="[unicode]">ucs,c</Item> + </Expand> + </Type> + + <Type Name="QString"> + <DisplayString>{((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub}</DisplayString> + <StringView>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub</StringView> + <Expand> + <Item Name="[size]">d->size</Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),c</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QStringRef"> + <Intrinsic Name="offset" Expression="(reinterpret_cast<char16_t*>(m_string->d)) + + m_string->d->offset / 2" /> + <DisplayString Condition="m_string == nullptr">{m_string,[m_size]} u""</DisplayString> + <DisplayString Condition="m_string != nullptr">{offset() + m_position,[m_size]}</DisplayString> + <Expand> + <Item Name="[position]" ExcludeView="simple">m_position</Item> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems Condition="m_string != nullptr"> + <Size>m_size</Size> + <ValuePointer>offset()+m_position</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QStringView"> + <DisplayString>{m_data,[m_size]}</DisplayString> + <StringView>m_data,[m_size]</StringView> + <Expand> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems> + <Size>m_size</Size> + <ValuePointer>m_data</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QByteArray"> + <DisplayString>{((reinterpret_cast<char*>(d)) + d->offset),sb}</DisplayString> + <StringView>((reinterpret_cast<char*>(d)) + d->offset),sb</StringView> + <Expand> + <Item Name="[size]">d->size</Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>((reinterpret_cast<char*>(d)) + d->offset),c</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QUrl"> + <Intrinsic Name="isEmpty" Expression="size==0"> + <Parameter Name="size" Type="int"/> + </Intrinsic> + <Intrinsic Name="memberOffset" Expression="sizeof(QAtomicInt) + sizeof(int) + (sizeof(QString) * count)"> + <Parameter Name="count" Type="int"/> + </Intrinsic> + <Intrinsic Name="scheme" Expression="*((QString*)(((char*)(d) + memberOffset(0))))" /> + <Intrinsic Name="username" Expression="*((QString*)(((char*)(d) + memberOffset(1))))" /> + <Intrinsic Name="password" Expression="*((QString*)(((char*)(d) + memberOffset(2))))" /> + <Intrinsic Name="host" Expression="*((QString*)(((char*)(d) + memberOffset(3))))" /> + <Intrinsic Name="path" Expression="*((QString*)(((char*)(d) + memberOffset(4))))" /> + <Intrinsic Name="query" Expression="*((QString*)(((char*)(d) + memberOffset(5))))" /> + <Intrinsic Name="fragment" Expression="*((QString*)(((char*)(d) + memberOffset(6))))" /> + + <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> + <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> + <Expand> + <Item Name="[scheme]">scheme()</Item> + <Item Name="[username]">username()</Item> + <Item Name="[password]">password()</Item> + <Item Name="[host]">host()</Item> + <Item Name="[path]">path()</Item> + <Item Name="[query]">query()</Item> + <Item Name="[fragment]">fragment()</Item> + </Expand> + </Type> + + <Type Name="QBitArray"> + <DisplayString>{{ size = {(d.d->size << 3) - *((reinterpret_cast<char*>(d.d)) + d.d->offset)} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d.d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>(d.d->size << 3) - *((reinterpret_cast<char*>(d.d)) + d.d->offset)</Size> + <ValueNode> + (*(reinterpret_cast<const unsigned char*>((reinterpret_cast<char*>(d.d)) + d.d->offset) + 1 + + ($i >> 3)) & (1 << ($i & 7))) != 0 + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="QVarLengthArray<*>"> + <AlternativeType Name="QVarLengthArray<*, int>"/> + <DisplayString>{{ size = {s} }}</DisplayString> + <Expand> + <Item Name="[capacity]">a</Item> + <ArrayItems> + <Size>s</Size> + <ValuePointer>ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QDate"> + <DisplayString>{{ julian day = {jd} }}</DisplayString> + <Expand></Expand> + </Type> + + <Type Name="QTime"> + <DisplayString + Condition="mds == 1">{{ millisecond = {mds} }}</DisplayString> + <DisplayString + Condition="mds != 1">{{ milliseconds = {mds} }}</DisplayString> + <Expand> + <Item Name="[hour]" + Condition="(mds / 3600000) == 1">mds / 3600000, d</Item> + <Item Name="[hours]" + Condition="(mds / 3600000) != 1">mds / 3600000, d</Item> + <Item Name="[minute]" + Condition="((mds % 3600000) / 60000) == 1">(mds % 3600000) / 60000, d</Item> + <Item Name="[minutes]" + Condition="((mds % 3600000) / 60000) != 1">(mds % 3600000) / 60000, d</Item> + <Item Name="[second]" + Condition="((mds / 1000) % 60) == 1">(mds / 1000) % 60, d</Item> + <Item Name="[seconds]" + Condition="((mds / 1000) % 60) != 1">(mds / 1000) % 60, d</Item> + <Item Name="[millisecond]" + Condition="(mds % 1000) == 1">mds % 1000, d</Item> + <Item Name="[milliseconds]" + Condition="(mds % 1000) != 1">mds % 1000, d</Item> + </Expand> + </Type> + + <Type Name="QRegularExpression"> + <DisplayString>{d.pattern}</DisplayString> + </Type> + + <Type Name="QSharedData"> + <Expand> + <Item Name="[referenced]">ref._q_value</Item> + </Expand> + </Type> + + <Type Name="QSharedPointer<*>"> + <DisplayString>strong reference to shared pointer of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">value == 0</Item> + <Item Name="[weak referenced]">d->weakref._q_value</Item> + <Item Name="[strong referenced]">d->strongref._q_value</Item> + </Expand> + </Type> + + <Type Name="QSharedDataPointer<*>"> + <DisplayString>pointer to implicit shared object of type {"$T1"}</DisplayString> + <Expand> + <ExpandedItem>d</ExpandedItem> + </Expand> + </Type> + + <Type Name="QExplicitlySharedDataPointer<*>"> + <DisplayString>pointer to explicit shared object of type {"$T1"}</DisplayString> + <Expand> + <ExpandedItem>d</ExpandedItem> + </Expand> + </Type> + + <Type Name="QPointer<*>"> + <DisplayString>guarded pointer to subclass of QObject of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">wp.d == 0 || wp.d->strongref._q_value == 0 || wp.value == 0</Item> + </Expand> + </Type> + + <Type Name="QWeakPointer<*>"> + <DisplayString>weak reference to shared pointer of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">d == 0 || d->strongref._q_value == 0 || value == 0</Item> + <Item Name="[weak referenced]">d->weakref._q_value</Item> + <Item Name="[strong referenced]">d->strongref._q_value</Item> + </Expand> + </Type> + + <Type Name="QScopedPointer<*>"> + <DisplayString>scoped pointer to a dynamically allocated object of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">!d</Item> + </Expand> + </Type> + + <Type Name="QScopedArrayPointer<*>"> + <DisplayString>scoped pointer to dynamically allocated array of objects of type {"$T1"}</DisplayString> + <Expand> + <Item Name="[is null]">!d</Item> + </Expand> + </Type> + + <Type Name="QPair<*,*>"> + <DisplayString>({first}, {second})</DisplayString> + <Expand> + <Item Name="[first]">first</Item> + <Item Name="[second]">second</Item> + </Expand> + </Type> + + <Type Name="QVector<*>"> + <AlternativeType Name="QStack<*>"></AlternativeType> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>($T1*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QList<*>"> + <AlternativeType Name="QQueue<*>"></AlternativeType> + <DisplayString>{{ size = {d->end - d->begin} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>d->end - d->begin</Size> + <ValueNode>*reinterpret_cast<$T1*>((sizeof($T1) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<$T1*>(d->array + d->begin + $i)) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="QStringList"> + <DisplayString>{{ size = {d->end - d->begin} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>d->end - d->begin</Size> + <ValueNode> + *reinterpret_cast<QString*>((sizeof(QString) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QString*>(d->array + d->begin + $i)) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="QList<QVariant>"> + <DisplayString>{{ size = {d->end - d->begin} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <IndexListItems> + <Size>d->end - d->begin</Size> + <ValueNode> + *reinterpret_cast<QVariant*>((sizeof(QVariant) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QVariant*>(d->array + d->begin + $i)) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="QLinkedList<*>"> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <LinkedListItems> + <Size>d->size</Size> + <HeadPointer>d->n</HeadPointer> + <NextPointer>n</NextPointer> + <ValueNode>(*(QLinkedListNode<$T1>*)this).t</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="QMapNode<*,*>"> + <DisplayString>({key}, {value})</DisplayString> + <Expand> + <Item Name="[key]">key</Item> + <Item Name="[value]">value</Item> + </Expand> + </Type> + + <Type Name="QMap<*,*>"> + <AlternativeType Name="QMultiMap<*,*>"/> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <TreeItems> + <Size>d->size</Size> + <HeadPointer>d->header.left</HeadPointer> + <LeftPointer>left</LeftPointer> + <RightPointer>right</RightPointer> + <ValueNode>*((QMapNode<$T1,$T2>*)this)</ValueNode> + </TreeItems> + </Expand> + </Type> + + <Type Name="QHashNode<*,*>"> + <DisplayString Condition="next == 0">(empty)</DisplayString> + <DisplayString Condition="next != 0">({key}, {value})</DisplayString> + <Expand> + <Item Name="[key]" Condition="next != 0">key</Item> + <Item Name="[value]" Condition="next != 0">value</Item> + <Item Name="[next]" Condition="next != 0">next</Item> + </Expand> + </Type> + + <Type Name="QHash<*,*>"> + <AlternativeType Name="QMultiHash<*,*>"/> + <DisplayString>{{ size = {d->size} }}</DisplayString> + <Expand> + <ArrayItems IncludeView="buckets"> + <Size>d->numBuckets</Size> + <ValuePointer>reinterpret_cast<Node **>(d->buckets)</ValuePointer> + </ArrayItems> + <CustomListItems ExcludeView="buckets"> + <Variable Name="n" InitialValue="d->numBuckets"/> + <Variable Name="bucket" InitialValue="d->buckets"/> + <Variable Name="node" InitialValue="d->buckets[0]"/> + <Variable Name="keyValuePair" InitialValue="reinterpret_cast<Node *>(0)"/> + <Size>d->size</Size> + <Loop> + <Break Condition="n == 0"/> + <Exec>node = *(bucket++)</Exec> + <Exec>--n</Exec> + <Loop> + <Break Condition="!node || !node->next"/> + <Exec>keyValuePair = reinterpret_cast<Node *>(node)</Exec> + <Item Name="[{keyValuePair->key}]">keyValuePair->value</Item> + <Exec>node = node->next</Exec> + </Loop> + </Loop> + </CustomListItems> + </Expand> + </Type> + + <Type Name="QHashNode<*,QHashDummyValue>"> + <DisplayString Condition="next == 0">(empty)</DisplayString> + <DisplayString Condition="next != 0">({key})</DisplayString> + <Expand> + <Item Name="[key]" Condition="next != 0">key</Item> + </Expand> + </Type> + + <Type Name="QSet<*>"> + <DisplayString>{{ size = {q_hash.d->size} }}</DisplayString> + <Expand> + <ExpandedItem>q_hash</ExpandedItem> + </Expand> + </Type> + + <Type Name="QCache<*,*>::Node"> + <DisplayString>({*keyPtr}, {*t})</DisplayString> + <Expand> + <Item Name="[key]">*keyPtr</Item> + <Item Name="[value]">*t</Item> + </Expand> + </Type> + + <Type Name="QCache<*,*>"> + <DisplayString>{{ size = {hash.d->size} }}</DisplayString> + <Expand> + <Item Name="[max coast]">mx</Item> + <Item Name="[total coast]">total</Item> + <Item Name="[referenced]">hash.d->ref.atomic._q_value</Item> + <LinkedListItems> + <Size>hash.d->size</Size> + <HeadPointer>f</HeadPointer> + <NextPointer>n</NextPointer> + <ValueNode>*((Node*)this)</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="QStandardItemPrivate"> + <Intrinsic Name="memberOffset" Expression="sizeof(QStandardItemModel *) + + sizeof(QStandardItem *) + + sizeof(int *) + + sizeof(int *) + + (sizeof(int) * count)"> + <Parameter Name="count" Type="int"/> + </Intrinsic> + <Intrinsic Name="rows" Expression="*((int*)(((char*)(this)) + memberOffset(0)))" /> + <Intrinsic Name="columns" Expression="*((int*)(((char*)(this)) + memberOffset(1)))" /> + </Type> + + <Type Name="QStandardItem"> + <DisplayString>{{ row count = {(*d_ptr.d).rows()}, column count = {(*d_ptr.d).columns()} }}</DisplayString> + <Expand> + <Item Name="[d]">d_ptr.d,!</Item> + <Item Name="[row count]">(*d_ptr.d).rows()</Item> + <Item Name="[column count]">(*d_ptr.d).columns()</Item> + </Expand> + </Type> + + <Type Name="QVariant"> + <!--Region DisplayString QVariant--> + + <DisplayString Condition="d.type == QMetaType::UnknownType">Invalid</DisplayString> + <DisplayString Condition="d.type == QMetaType::Bool">{d.data.b}</DisplayString> + <DisplayString Condition="d.type == QMetaType::Int">{d.data.i}</DisplayString> + <DisplayString Condition="d.type == QMetaType::UInt">{d.data.u}</DisplayString> + <DisplayString Condition="d.type == QMetaType::LongLong">{d.data.ll}</DisplayString> + <DisplayString Condition="d.type == QMetaType::ULongLong">{d.data.ull}</DisplayString> + <DisplayString Condition="d.type == QMetaType::Double">{d.data.d}</DisplayString> + <DisplayString Condition="d.type == QMetaType::QChar">{d.data.c}</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVariantMap"> + {*((QMap<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QVariantList"> + {*((QList<QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QString"> + {*((QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QStringList"> + {*((QStringList*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QByteArray"> + {*((QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QBitArray"> + {*((QBitArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QDate"> + {*((QDate*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QTime"> + {*((QTime*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QDateTime">DateTime</DisplayString> + <DisplayString Condition="d.type == QMetaType::QUrl">Url</DisplayString> + <DisplayString Condition="d.type == QMetaType::QLocale">Locale</DisplayString> + <DisplayString Condition="d.type == QMetaType::QRect"> + {*((QRect*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QRectF"> + {*((QRectF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QSize"> + {*((QSize*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QSizeF"> + {*((QSizeF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QLine"> + {*((QLine*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QLineF"> + {*((QLineF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QPoint"> + {*((QPoint*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QPointF"> + {*((QPointF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QRegExp">RegExp</DisplayString> + <DisplayString Condition="d.type == QMetaType::QRegularExpression">RegularExpression</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVariantHash"> + {*((QHash<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + </DisplayString> + <DisplayString Condition="d.type == QMetaType::QEasingCurve">EasingCurve</DisplayString> + <DisplayString Condition="d.type == QMetaType::QUuid">Uuid</DisplayString> + <DisplayString Condition="d.type == QMetaType::QModelIndex">ModelIndex</DisplayString> + <DisplayString Condition="d.type == QMetaType::LastCoreType">LastCoreType</DisplayString> + <DisplayString Condition="d.type == QMetaType::QFont">Font</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPixmap">Pixmap</DisplayString> + <DisplayString Condition="d.type == QMetaType::QBrush">Brush</DisplayString> + <DisplayString Condition="d.type == QMetaType::QColor">Color</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPalette">Palette</DisplayString> + <DisplayString Condition="d.type == QMetaType::QImage">Image</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPolygon">Polygon</DisplayString> + <DisplayString Condition="d.type == QMetaType::QRegion">Region</DisplayString> + <DisplayString Condition="d.type == QMetaType::QBitmap">Bitmap</DisplayString> + <DisplayString Condition="d.type == QMetaType::QCursor">Cursor</DisplayString> + <DisplayString Condition="d.type == QMetaType::QKeySequence">KeySequence</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPen">Pen</DisplayString> + <DisplayString Condition="d.type == QMetaType::QTextLength">TextLength</DisplayString> + <DisplayString Condition="d.type == QMetaType::QTextFormat">TextFormat</DisplayString> + <DisplayString Condition="d.type == QMetaType::QMatrix">Matrix</DisplayString> + <DisplayString Condition="d.type == QMetaType::QTransform">Transform</DisplayString> + <DisplayString Condition="d.type == QMetaType::QMatrix4x4">Matrix4x4</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVector2D">Vector2D</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVector3D">Vector3D</DisplayString> + <DisplayString Condition="d.type == QMetaType::QVector4D">Vector4D</DisplayString> + <DisplayString Condition="d.type == QMetaType::QQuaternion">Quaternion</DisplayString> + <DisplayString Condition="d.type == QMetaType::QPolygonF">PolygonF</DisplayString> + <DisplayString Condition="d.type == QMetaType::QIcon">Icon</DisplayString> + <DisplayString Condition="d.type == QMetaType::LastGuiType">LastGuiType</DisplayString> + <DisplayString Condition="d.type == QMetaType::QSizePolicy">SizePolicy</DisplayString> + <DisplayString Condition="d.type == QMetaType::User">UserType</DisplayString> + <DisplayString Condition="d.type == 0xffffffff">LastType</DisplayString> + + <!--End region DisplayString QVariant--> + + <!--Region DisplayView QVariant--> + + <StringView Condition="d.type == QMetaType::QChar">d.data.c</StringView> + + <StringView Condition="d.type == QMetaType::QString"> + *((QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </StringView> + + <StringView Condition="d.type == QMetaType::QByteArray"> + *((QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </StringView> + + <!--End region DisplayView QVariant--> + + <!--Region Expand QVariant--> + + <Expand> + <ExpandedItem Condition="d.type == QMetaType::QVariantMap"> + *((QMap<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QVariantList"> + *((QList<QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QString"> + *((QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QStringList"> + *((QStringList*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QByteArray"> + *((QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QBitArray"> + *((QBitArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QDate"> + *((QDate*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QTime"> + *((QTime*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QRect"> + *((QRect*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QRectF"> + *((QRectF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QSize"> + *((QSize*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QSizeF"> + *((QSizeF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QLine"> + *((QLine*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QLineF"> + *((QLineF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QPoint"> + *((QPoint*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QPointF"> + *((QPointF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + <ExpandedItem Condition="d.type == QMetaType::QVariantHash"> + *((QHash<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + </ExpandedItem> + </Expand> + + <!--End region Expand QVariant--> + </Type> + +</AutoVisualizer> diff --git a/template/qt6.natvis b/template/qt6.natvis new file mode 100644 index 0000000..94c2260 --- /dev/null +++ b/template/qt6.natvis @@ -0,0 +1,735 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--************************************************************************************************ + Copyright (C) 2023 The Qt Company Ltd. + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +*************************************************************************************************--> + +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + + <Type Name="QPropertyData<*>"> + <DisplayString>{val}</DisplayString> + <Expand> + <Item Name="[value]">val</Item> + </Expand> + </Type> + + <Type Name="QQuickItemPrivate"> + <Intrinsic Name="_hasExtraData" Expression="extra.d.d != 0" /> + <Intrinsic Name="_extraData" Expression="(*(ExtraData*)extra.d.d)" /> + <Intrinsic Name="_objectName" Expression="(extraData->objectName).val.d.ptr" /> + <DisplayString Condition="_hasExtraData()">{{ x = {x,g}, y = {y,g}, z = {_extraData().z,g}, width = {width,g}, height = {height,g} }}</DisplayString> + <DisplayString>{{ x = {x,g}, y = {y,g}, width = {width,g}, height = {height,g} }}</DisplayString> + <Expand> + <Item Name="x">x</Item> + <Item Name="y">y</Item> + <Item Name="z" Condition="_hasExtraData()">_extraData().z</Item> + <Item Name="scale" Condition="_hasExtraData()">_extraData().scale</Item> + <Item Name="rotation" Condition="_hasExtraData()">_extraData().rotation</Item> + <Item Name="opacity" Condition="_hasExtraData()">_extraData().opacity</Item> + <Item Name="width">width</Item> + <Item Name="height">height</Item> + <Item Name="implicitWidth">implicitWidth</Item> + <Item Name="implicitHeight">implicitHeight</Item> + <Item Name="visible">effectiveVisible</Item> + <Item Name="enabled">explicitEnable</Item> + <Item Name="objectName" Condition="_objectName() != 0">_objectName(),na</Item> + <Item Name="parentItem">parentItem</Item> + <Item Name="childItems">childItems, nr</Item> + </Expand> + </Type> + + <Type Name="QQuickItem"> + <DisplayString>{d_ptr.d,na}</DisplayString> + <Expand> + <ExpandedItem>d_ptr.d</ExpandedItem> + </Expand> + </Type> + + <Type Name="QUuid"> + <DisplayString>{{{data1,Xb}-{data2,Xb}-{data3,Xb}-{(data4[0]),nvoXb}{(data4[1]),nvoXb}-{(data4[2]),nvoXb}{(data4[3]),nvoXb}{(data4[4]),nvoXb}{(data4[5]),nvoXb}{(data4[6]),nvoXb}{(data4[7]),nvoXb}}}</DisplayString> + </Type> + + <Type Name="QSpecialInteger<*>"> + <DisplayString>{val}</DisplayString> + <Expand> + <Item Name="[value]">val</Item> + </Expand> + </Type> + + <Type Name="QBasicAtomicInteger<*>"> + <DisplayString>{_q_value}</DisplayString> + <Expand> + <Item Name="[value]">_q_value</Item> + </Expand> + </Type> + + <Type Name="QBasicAtomicPointer<*>"> + <Intrinsic Name="isNull" Expression="value()==0" /> + <Intrinsic Name="value" Expression="_q_value.value()" /> + <DisplayString Condition="isNull()">empty</DisplayString> + <DisplayString Condition="!isNull()">{_q_value}</DisplayString> + <Expand> + <Item Name=" " Condition="!isNull()">*value()</Item> + </Expand> + </Type> + + <Type Name="QPoint"> + <AlternativeType Name="QPointF"/> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name="QRect"> + <DisplayString>{{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }}</DisplayString> + <Expand> + <Item Name="[x]">x1</Item> + <Item Name="[y]">y1</Item> + <Item Name="[width]">x2 - x1 + 1</Item> + <Item Name="[height]">y2 - y1 + 1</Item> + </Expand> + </Type> + + <Type Name="QRectF"> + <DisplayString>{{ x = {xp}, y = {yp}, width = {w}, height = {h} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[width]">w</Item> + <Item Name="[height]">h</Item> + </Expand> + </Type> + + <Type Name="QSize"> + <AlternativeType Name="QSizeF"/> + <DisplayString>{{ width = {wd}, height = {ht} }}</DisplayString> + <Expand> + <Item Name="[width]">wd</Item> + <Item Name="[height]">ht</Item> + </Expand> + </Type> + + <Type Name="QLine"> + <AlternativeType Name="QLineF"/> + <DisplayString>{{ start point = {pt1}, end point = {pt2} }}</DisplayString> + <Expand> + <Synthetic Name="[start point]"> + <DisplayString>{pt1}</DisplayString> + <Expand> + <ExpandedItem>pt1</ExpandedItem> + </Expand> + </Synthetic> + <Synthetic Name="[end point]"> + <DisplayString>{pt2}</DisplayString> + <Expand> + <ExpandedItem>pt2</ExpandedItem> + </Expand> + </Synthetic> + + </Expand> + </Type> + + <Type Name="QPolygon"> + <DisplayString>{{ size={d->size} }}</DisplayString> + <Expand> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPoint*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QPolygonF"> + <DisplayString>{{ size={d->size} }}</DisplayString> + <Expand> + <Item Name="[closed]"> + d->size > 0 + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).xp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).xp) + && ((((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[0]).yp + == (((QPointF*)((reinterpret_cast<char*>(d)) + d->offset)[d->size - 1]).yp) + </Item> + <Item Name="[referenced]">d->ref.atomic._q_value</Item> + <ArrayItems> + <Size>d->size</Size> + <ValuePointer>(QPointF*)((reinterpret_cast<char*>(d)) + d->offset)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QVector2D"> + <DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + </Expand> + </Type> + + <Type Name="QVector3D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + </Expand> + </Type> + + <Type Name="QVector4D"> + <DisplayString>{{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }}</DisplayString> + <Expand> + <Item Name="[x]">xp</Item> + <Item Name="[y]">yp</Item> + <Item Name="[z]">zp</Item> + <Item Name="[w]">wp</Item> + </Expand> + </Type> + + <Type Name="QMatrix"> + <DisplayString> + {{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">_m11</Item> + <Item Name="[m12]">_m12</Item> + <Item Name="[m21]">_m21</Item> + <Item Name="[m22]">_m22</Item> + <Item Name="[dx]">_dx</Item> + <Item Name="[dy]">_dy</Item> + </Expand> + </Type> + + <Type Name="QMatrix4x4"> + <DisplayString> + {{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }} + </DisplayString> + <Expand> + <Item Name="[m11]">m[0][0]</Item> + <Item Name="[m12]">m[1][0]</Item> + <Item Name="[m13]">m[2][0]</Item> + <Item Name="[m14]">m[3][0]</Item> + <Item Name="[m21]">m[0][1]</Item> + <Item Name="[m22]">m[1][1]</Item> + <Item Name="[m23]">m[2][1]</Item> + <Item Name="[m24]">m[3][1]</Item> + <Item Name="[m31]">m[0][2]</Item> + <Item Name="[m32]">m[1][2]</Item> + <Item Name="[m33]">m[2][2]</Item> + <Item Name="[m34]">m[3][2]</Item> + <Item Name="[m41]">m[0][3]</Item> + <Item Name="[m42]">m[1][3]</Item> + <Item Name="[m43]">m[2][3]</Item> + <Item Name="[m44]">m[3][3]</Item> + </Expand> + </Type> + + <Type Name="QSizePolicy"> + <DisplayString> + {{ horizontal = {static_cast<Policy>(bits.horPolicy)}, vertical = {static_cast<Policy>(bits.verPolicy)}, type = {ControlType(1 << bits.ctype)} }} + </DisplayString> + <Expand> + <Synthetic Name="[vertical policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.verPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[horizontal policy]"> + <DisplayString>QSizePolicy::Policy::{static_cast<Policy>(bits.horPolicy)}</DisplayString> + </Synthetic> + <Synthetic Name="[control type]"> + <DisplayString>QSizePolicy::ControlType::{ControlType(1 << bits.ctype)}</DisplayString> + </Synthetic> + <Synthetic Name="[expanding directions]"> + <DisplayString + Condition="(static_cast<Policy>(bits.verPolicy) & ExpandFlag)"> + Qt::Vertical (2) + </DisplayString> + <DisplayString + Condition="(static_cast<Policy>(bits.horPolicy) & ExpandFlag)"> + Qt::Horizontal (1) + </DisplayString> + </Synthetic> + <Item Name="[vertical stretch]">static_cast<int>(bits.verStretch)</Item> + <Item Name="[horizontal stretch]">static_cast<int>(bits.horStretch)</Item> + <Item Name="[has height for width]">bits.hfw == 1</Item> + <Item Name="[has width for height]">bits.wfh == 1</Item> + </Expand> + </Type> + + <Type Name="QChar"> + <DisplayString>{ucs,c}</DisplayString> + <StringView>ucs,c</StringView> + <Expand> + <Item Name="[latin 1]">ucs > 0xff ? '\0' : char(ucs),c</Item> + <Item Name="[unicode]">ucs,c</Item> + </Expand> + </Type> + + <Type Name="QString"> + <DisplayString>"{(reinterpret_cast<unsigned short*>(d.ptr)),sub}"</DisplayString> + <StringView>(reinterpret_cast<unsigned short*>(d.ptr)),sub</StringView> + <Expand> + <Item Name="[size]">d.size</Item> + <ArrayItems> + <Size>d.size</Size> + <ValuePointer>d.ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QStringRef"> + <DisplayString Condition="m_string == nullptr">{m_string,[m_size]} u""</DisplayString> + <DisplayString Condition="m_string != nullptr">{m_string->d.ptr+m_position,[m_size]}</DisplayString> + <StringView Condition="m_string == nullptr">""</StringView> + <StringView Condition="m_string != nullptr">m_string,[m_position+m_size]</StringView> + <Expand> + <Item Name="[position]" ExcludeView="simple">m_position</Item> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems Condition="m_string != nullptr"> + <Size>m_size</Size> + <ValuePointer>m_string->d.ptr+m_position</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QStringView"> + <DisplayString>{m_data,[m_size]}</DisplayString> + <StringView>m_data,[m_size]</StringView> + <Expand> + <Item Name="[size]" ExcludeView="simple">m_size</Item> + <ArrayItems> + <Size>m_size</Size> + <ValuePointer>m_data</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QByteArray"> + <DisplayString>"{((reinterpret_cast<char*>(d.ptr))),sb}"</DisplayString> + <StringView>((reinterpret_cast<char*>(d.ptr))),sb</StringView> + <Expand> + <Item Name="[size]">d.size</Item> + <ArrayItems> + <Size>d.size</Size> + <ValuePointer>d.ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QUrl"> + <Intrinsic Name="isEmpty" Expression="size==0"> + <Parameter Name="size" Type="int"/> + </Intrinsic> + <Intrinsic Name="memberOffset" Expression="sizeof(QAtomicInt) + sizeof(int) + (sizeof(QString) * count)"> + <Parameter Name="count" Type="int"/> + </Intrinsic> + <Intrinsic Name="scheme" Expression="*((QString*)(((char*)(d) + memberOffset(0))))" /> + <Intrinsic Name="username" Expression="*((QString*)(((char*)(d) + memberOffset(1))))" /> + <Intrinsic Name="password" Expression="*((QString*)(((char*)(d) + memberOffset(2))))" /> + <Intrinsic Name="host" Expression="*((QString*)(((char*)(d) + memberOffset(3))))" /> + <Intrinsic Name="path" Expression="*((QString*)(((char*)(d) + memberOffset(4))))" /> + <Intrinsic Name="query" Expression="*((QString*)(((char*)(d) + memberOffset(5))))" /> + <Intrinsic Name="fragment" Expression="*((QString*)(((char*)(d) + memberOffset(6))))" /> + + <DisplayString Condition="!isEmpty(scheme().d->size)">{scheme()}://{host()}{path()}</DisplayString> + <DisplayString Condition="isEmpty(scheme().d->size)">{path()}</DisplayString> + <Expand> + <Item Name="[scheme]">scheme()</Item> + <Item Name="[username]">username()</Item> + <Item Name="[password]">password()</Item> + <Item Name="[host]">host()</Item> + <Item Name="[path]">path()</Item> + <Item Name="[query]">query()</Item> + <Item Name="[fragment]">fragment()</Item> + </Expand> + </Type> + + <Type Name="QDate"> + <DisplayString>{{ julian day = {jd} }}</DisplayString> + </Type> + + <Type Name="QTime"> + <Intrinsic Name="hour" Expression="mds / 3600000" /> + <Intrinsic Name="minute" Expression="(mds % 3600000) / 60000" /> + <Intrinsic Name="second" Expression="(mds / 1000) % 60" /> + <Intrinsic Name="millisecond" Expression="mds % 1000" /> + <DisplayString Condition="mds == 1">{{ millisecond = {mds} }}</DisplayString> + <DisplayString Condition="mds != 1">{{ milliseconds = {mds} }}</DisplayString> + <Expand> + <Item Name="[hour]" + Condition="(mds / 3600000) == 1">hour(), d</Item> + <Item Name="[hours]" + Condition="(mds / 3600000) != 1">hour(), d</Item> + <Item Name="[minute]" + Condition="((mds % 3600000) / 60000) == 1">minute(), d</Item> + <Item Name="[minutes]" + Condition="((mds % 3600000) / 60000) != 1">minute(), d</Item> + <Item Name="[second]" + Condition="((mds / 1000) % 60) == 1">second(), d</Item> + <Item Name="[seconds]" + Condition="((mds / 1000) % 60) != 1">second(), d</Item> + <Item Name="[millisecond]" + Condition="(mds % 1000) == 1">millisecond(), d</Item> + <Item Name="[milliseconds]" + Condition="(mds % 1000) != 1">millisecond(), d</Item> + </Expand> + </Type> + + <Type Name="QPair<*,*>"> + <DisplayString>({first}, {second})</DisplayString> + <Expand> + <Item Name="[first]">first</Item> + <Item Name="[second]">second</Item> + </Expand> + </Type> + + <Type Name="QList<*>"> + <AlternativeType Name="QVector<*>"/> + <DisplayString>{{ size={d.size} }}</DisplayString> + <Expand> + <ArrayItems> + <Size>d.size</Size> + <ValuePointer>reinterpret_cast<$T1*>(d.ptr)</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QVarLengthArray<*>"> + <DisplayString>{{ size={s} }}</DisplayString> + <Expand> + <Item Name="[capacity]">a</Item> + <ArrayItems> + <Size>s</Size> + <ValuePointer>ptr</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="QMap<*,*>"> + <AlternativeType Name="QMultiMap<*,*>"/> + <DisplayString>{{ size={d.d->m._Mypair._Myval2._Myval2._Mysize} }}</DisplayString> + <Expand> + <TreeItems> + <Size>d.d->m._Mypair._Myval2._Myval2._Mysize</Size> + <HeadPointer>d.d->m._Mypair._Myval2._Myval2._Myhead->_Parent</HeadPointer> + <LeftPointer>_Left</LeftPointer> + <RightPointer>_Right</RightPointer> + <ValueNode Condition="_Isnil == 0" Name="[{_Myval.first}]">_Myval,view(MapHelper)</ValueNode> + </TreeItems> + </Expand> + </Type> + + <Type Name="std::pair<*, *>" IncludeView="MapHelper"> + <DisplayString>{second}</DisplayString> + </Type> + + <Type Name="QHashPrivate::Node<*,*>"> + <DisplayString>{value}</DisplayString> + <Expand> + <Item Name="key">key</Item> + <Item Name="value">value</Item> + </Expand> + </Type> + + <Type Name="QHashPrivate::MultiNode<*,*>"> + <DisplayString Condition="value->next == 0">{value->value}</DisplayString> + <DisplayString Condition="value->next != 0 && value->next->next == 0">({value->value}, {value->next->value})</DisplayString> + <DisplayString Condition="value->next != 0 && value->next->next != 0">({value->value}, {value->next->value}, ...)</DisplayString> + <Expand> + <LinkedListItems> + <HeadPointer>value</HeadPointer> + <NextPointer>next</NextPointer> + <ValueNode>value</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="QHash<*,*>"> + <AlternativeType Name="QMultiHash<*,*>"/> + <Intrinsic Name="getOffset" Category="Method" Expression="d->spans[span].offsets[offset]"> + <Parameter Name="span" Type="int" /> + <Parameter Name="offset" Type="int" /> + </Intrinsic> + <Intrinsic Name="getKey" Category="Method" Expression="((Node*)(char *)&(d->spans[span].entries[d->spans[span].offsets[offset]].storage))->key"> + <Parameter Name="span" Type="int" /> + <Parameter Name="offset" Type="int" /> + </Intrinsic> + <Intrinsic Name="getNode" Category="Method" Expression="*((Node*)(char *)&(d->spans[span].entries[d->spans[span].offsets[offset]].storage))"> + <Parameter Name="span" Type="int" /> + <Parameter Name="offset" Type="int" /> + </Intrinsic> + + <DisplayString>{{ size={d->size} }}</DisplayString> + <Expand> + <CustomListItems MaxItemsPerView="5000"> + <Variable Name="iSpan" InitialValue="0" /> + <Variable Name="spanCount" InitialValue="d->numBuckets" /> + <Size>d->size</Size> + <Loop> + <If Condition="iSpan != spanCount"> + <Item Name="[{getKey(iSpan, 0)}]" Condition="getOffset(iSpan, 0) != 255">getNode(iSpan, 0)</Item> + <Item Name="[{getKey(iSpan, 1)}]" Condition="getOffset(iSpan, 1) != 255">getNode(iSpan, 1)</Item> + <Item Name="[{getKey(iSpan, 2)}]" Condition="getOffset(iSpan, 2) != 255">getNode(iSpan, 2)</Item> + <Item Name="[{getKey(iSpan, 3)}]" Condition="getOffset(iSpan, 3) != 255">getNode(iSpan, 3)</Item> + <Item Name="[{getKey(iSpan, 4)}]" Condition="getOffset(iSpan, 4) != 255">getNode(iSpan, 4)</Item> + <Item Name="[{getKey(iSpan, 5)}]" Condition="getOffset(iSpan, 5) != 255">getNode(iSpan, 5)</Item> + <Item Name="[{getKey(iSpan, 6)}]" Condition="getOffset(iSpan, 6) != 255">getNode(iSpan, 6)</Item> + <Item Name="[{getKey(iSpan, 7)}]" Condition="getOffset(iSpan, 7) != 255">getNode(iSpan, 7)</Item> + <Item Name="[{getKey(iSpan, 8)}]" Condition="getOffset(iSpan, 8) != 255">getNode(iSpan, 8)</Item> + <Item Name="[{getKey(iSpan, 9)}]" Condition="getOffset(iSpan, 9) != 255">getNode(iSpan, 9)</Item> + <Item Name="[{getKey(iSpan, 10)}]" Condition="getOffset(iSpan, 10) != 255">getNode(iSpan, 10)</Item> + <Item Name="[{getKey(iSpan, 11)}]" Condition="getOffset(iSpan, 11) != 255">getNode(iSpan, 11)</Item> + <Item Name="[{getKey(iSpan, 12)}]" Condition="getOffset(iSpan, 12) != 255">getNode(iSpan, 12)</Item> + <Item Name="[{getKey(iSpan, 13)}]" Condition="getOffset(iSpan, 13) != 255">getNode(iSpan, 13)</Item> + <Item Name="[{getKey(iSpan, 14)}]" Condition="getOffset(iSpan, 14) != 255">getNode(iSpan, 14)</Item> + <Item Name="[{getKey(iSpan, 15)}]" Condition="getOffset(iSpan, 15) != 255">getNode(iSpan, 15)</Item> + <Item Name="[{getKey(iSpan, 16)}]" Condition="getOffset(iSpan, 16) != 255">getNode(iSpan, 16)</Item> + <Item Name="[{getKey(iSpan, 17)}]" Condition="getOffset(iSpan, 17) != 255">getNode(iSpan, 17)</Item> + <Item Name="[{getKey(iSpan, 18)}]" Condition="getOffset(iSpan, 18) != 255">getNode(iSpan, 18)</Item> + <Item Name="[{getKey(iSpan, 19)}]" Condition="getOffset(iSpan, 19) != 255">getNode(iSpan, 19)</Item> + <Item Name="[{getKey(iSpan, 20)}]" Condition="getOffset(iSpan, 20) != 255">getNode(iSpan, 20)</Item> + <Item Name="[{getKey(iSpan, 21)}]" Condition="getOffset(iSpan, 21) != 255">getNode(iSpan, 21)</Item> + <Item Name="[{getKey(iSpan, 22)}]" Condition="getOffset(iSpan, 22) != 255">getNode(iSpan, 22)</Item> + <Item Name="[{getKey(iSpan, 23)}]" Condition="getOffset(iSpan, 23) != 255">getNode(iSpan, 23)</Item> + <Item Name="[{getKey(iSpan, 24)}]" Condition="getOffset(iSpan, 24) != 255">getNode(iSpan, 24)</Item> + <Item Name="[{getKey(iSpan, 25)}]" Condition="getOffset(iSpan, 25) != 255">getNode(iSpan, 25)</Item> + <Item Name="[{getKey(iSpan, 26)}]" Condition="getOffset(iSpan, 26) != 255">getNode(iSpan, 26)</Item> + <Item Name="[{getKey(iSpan, 27)}]" Condition="getOffset(iSpan, 27) != 255">getNode(iSpan, 27)</Item> + <Item Name="[{getKey(iSpan, 28)}]" Condition="getOffset(iSpan, 28) != 255">getNode(iSpan, 28)</Item> + <Item Name="[{getKey(iSpan, 29)}]" Condition="getOffset(iSpan, 29) != 255">getNode(iSpan, 29)</Item> + <Item Name="[{getKey(iSpan, 30)}]" Condition="getOffset(iSpan, 30) != 255">getNode(iSpan, 30)</Item> + <Item Name="[{getKey(iSpan, 31)}]" Condition="getOffset(iSpan, 31) != 255">getNode(iSpan, 31)</Item> + <Item Name="[{getKey(iSpan, 32)}]" Condition="getOffset(iSpan, 32) != 255">getNode(iSpan, 32)</Item> + <Item Name="[{getKey(iSpan, 33)}]" Condition="getOffset(iSpan, 33) != 255">getNode(iSpan, 33)</Item> + <Item Name="[{getKey(iSpan, 34)}]" Condition="getOffset(iSpan, 34) != 255">getNode(iSpan, 34)</Item> + <Item Name="[{getKey(iSpan, 35)}]" Condition="getOffset(iSpan, 35) != 255">getNode(iSpan, 35)</Item> + <Item Name="[{getKey(iSpan, 36)}]" Condition="getOffset(iSpan, 36) != 255">getNode(iSpan, 36)</Item> + <Item Name="[{getKey(iSpan, 37)}]" Condition="getOffset(iSpan, 37) != 255">getNode(iSpan, 37)</Item> + <Item Name="[{getKey(iSpan, 38)}]" Condition="getOffset(iSpan, 38) != 255">getNode(iSpan, 38)</Item> + <Item Name="[{getKey(iSpan, 39)}]" Condition="getOffset(iSpan, 39) != 255">getNode(iSpan, 39)</Item> + <Item Name="[{getKey(iSpan, 40)}]" Condition="getOffset(iSpan, 40) != 255">getNode(iSpan, 40)</Item> + <Item Name="[{getKey(iSpan, 41)}]" Condition="getOffset(iSpan, 41) != 255">getNode(iSpan, 41)</Item> + <Item Name="[{getKey(iSpan, 42)}]" Condition="getOffset(iSpan, 42) != 255">getNode(iSpan, 42)</Item> + <Item Name="[{getKey(iSpan, 43)}]" Condition="getOffset(iSpan, 43) != 255">getNode(iSpan, 43)</Item> + <Item Name="[{getKey(iSpan, 44)}]" Condition="getOffset(iSpan, 44) != 255">getNode(iSpan, 44)</Item> + <Item Name="[{getKey(iSpan, 45)}]" Condition="getOffset(iSpan, 45) != 255">getNode(iSpan, 45)</Item> + <Item Name="[{getKey(iSpan, 46)}]" Condition="getOffset(iSpan, 46) != 255">getNode(iSpan, 46)</Item> + <Item Name="[{getKey(iSpan, 47)}]" Condition="getOffset(iSpan, 47) != 255">getNode(iSpan, 47)</Item> + <Item Name="[{getKey(iSpan, 48)}]" Condition="getOffset(iSpan, 48) != 255">getNode(iSpan, 48)</Item> + <Item Name="[{getKey(iSpan, 49)}]" Condition="getOffset(iSpan, 49) != 255">getNode(iSpan, 49)</Item> + <Item Name="[{getKey(iSpan, 50)}]" Condition="getOffset(iSpan, 50) != 255">getNode(iSpan, 50)</Item> + <Item Name="[{getKey(iSpan, 51)}]" Condition="getOffset(iSpan, 51) != 255">getNode(iSpan, 51)</Item> + <Item Name="[{getKey(iSpan, 52)}]" Condition="getOffset(iSpan, 52) != 255">getNode(iSpan, 52)</Item> + <Item Name="[{getKey(iSpan, 53)}]" Condition="getOffset(iSpan, 53) != 255">getNode(iSpan, 53)</Item> + <Item Name="[{getKey(iSpan, 54)}]" Condition="getOffset(iSpan, 54) != 255">getNode(iSpan, 54)</Item> + <Item Name="[{getKey(iSpan, 55)}]" Condition="getOffset(iSpan, 55) != 255">getNode(iSpan, 55)</Item> + <Item Name="[{getKey(iSpan, 56)}]" Condition="getOffset(iSpan, 56) != 255">getNode(iSpan, 56)</Item> + <Item Name="[{getKey(iSpan, 57)}]" Condition="getOffset(iSpan, 57) != 255">getNode(iSpan, 57)</Item> + <Item Name="[{getKey(iSpan, 58)}]" Condition="getOffset(iSpan, 58) != 255">getNode(iSpan, 58)</Item> + <Item Name="[{getKey(iSpan, 59)}]" Condition="getOffset(iSpan, 59) != 255">getNode(iSpan, 59)</Item> + <Item Name="[{getKey(iSpan, 60)}]" Condition="getOffset(iSpan, 60) != 255">getNode(iSpan, 60)</Item> + <Item Name="[{getKey(iSpan, 61)}]" Condition="getOffset(iSpan, 61) != 255">getNode(iSpan, 61)</Item> + <Item Name="[{getKey(iSpan, 62)}]" Condition="getOffset(iSpan, 62) != 255">getNode(iSpan, 62)</Item> + <Item Name="[{getKey(iSpan, 63)}]" Condition="getOffset(iSpan, 63) != 255">getNode(iSpan, 63)</Item> + <Item Name="[{getKey(iSpan, 64)}]" Condition="getOffset(iSpan, 64) != 255">getNode(iSpan, 64)</Item> + <Item Name="[{getKey(iSpan, 65)}]" Condition="getOffset(iSpan, 65) != 255">getNode(iSpan, 65)</Item> + <Item Name="[{getKey(iSpan, 66)}]" Condition="getOffset(iSpan, 66) != 255">getNode(iSpan, 66)</Item> + <Item Name="[{getKey(iSpan, 67)}]" Condition="getOffset(iSpan, 67) != 255">getNode(iSpan, 67)</Item> + <Item Name="[{getKey(iSpan, 68)}]" Condition="getOffset(iSpan, 68) != 255">getNode(iSpan, 68)</Item> + <Item Name="[{getKey(iSpan, 69)}]" Condition="getOffset(iSpan, 69) != 255">getNode(iSpan, 69)</Item> + <Item Name="[{getKey(iSpan, 70)}]" Condition="getOffset(iSpan, 70) != 255">getNode(iSpan, 70)</Item> + <Item Name="[{getKey(iSpan, 71)}]" Condition="getOffset(iSpan, 71) != 255">getNode(iSpan, 71)</Item> + <Item Name="[{getKey(iSpan, 72)}]" Condition="getOffset(iSpan, 72) != 255">getNode(iSpan, 72)</Item> + <Item Name="[{getKey(iSpan, 73)}]" Condition="getOffset(iSpan, 73) != 255">getNode(iSpan, 73)</Item> + <Item Name="[{getKey(iSpan, 74)}]" Condition="getOffset(iSpan, 74) != 255">getNode(iSpan, 74)</Item> + <Item Name="[{getKey(iSpan, 75)}]" Condition="getOffset(iSpan, 75) != 255">getNode(iSpan, 75)</Item> + <Item Name="[{getKey(iSpan, 76)}]" Condition="getOffset(iSpan, 76) != 255">getNode(iSpan, 76)</Item> + <Item Name="[{getKey(iSpan, 77)}]" Condition="getOffset(iSpan, 77) != 255">getNode(iSpan, 77)</Item> + <Item Name="[{getKey(iSpan, 78)}]" Condition="getOffset(iSpan, 78) != 255">getNode(iSpan, 78)</Item> + <Item Name="[{getKey(iSpan, 79)}]" Condition="getOffset(iSpan, 79) != 255">getNode(iSpan, 79)</Item> + <Item Name="[{getKey(iSpan, 80)}]" Condition="getOffset(iSpan, 80) != 255">getNode(iSpan, 80)</Item> + <Item Name="[{getKey(iSpan, 81)}]" Condition="getOffset(iSpan, 81) != 255">getNode(iSpan, 81)</Item> + <Item Name="[{getKey(iSpan, 82)}]" Condition="getOffset(iSpan, 82) != 255">getNode(iSpan, 82)</Item> + <Item Name="[{getKey(iSpan, 83)}]" Condition="getOffset(iSpan, 83) != 255">getNode(iSpan, 83)</Item> + <Item Name="[{getKey(iSpan, 84)}]" Condition="getOffset(iSpan, 84) != 255">getNode(iSpan, 84)</Item> + <Item Name="[{getKey(iSpan, 85)}]" Condition="getOffset(iSpan, 85) != 255">getNode(iSpan, 85)</Item> + <Item Name="[{getKey(iSpan, 86)}]" Condition="getOffset(iSpan, 86) != 255">getNode(iSpan, 86)</Item> + <Item Name="[{getKey(iSpan, 87)}]" Condition="getOffset(iSpan, 87) != 255">getNode(iSpan, 87)</Item> + <Item Name="[{getKey(iSpan, 88)}]" Condition="getOffset(iSpan, 88) != 255">getNode(iSpan, 88)</Item> + <Item Name="[{getKey(iSpan, 89)}]" Condition="getOffset(iSpan, 89) != 255">getNode(iSpan, 89)</Item> + <Item Name="[{getKey(iSpan, 90)}]" Condition="getOffset(iSpan, 90) != 255">getNode(iSpan, 90)</Item> + <Item Name="[{getKey(iSpan, 91)}]" Condition="getOffset(iSpan, 91) != 255">getNode(iSpan, 91)</Item> + <Item Name="[{getKey(iSpan, 92)}]" Condition="getOffset(iSpan, 92) != 255">getNode(iSpan, 92)</Item> + <Item Name="[{getKey(iSpan, 93)}]" Condition="getOffset(iSpan, 93) != 255">getNode(iSpan, 93)</Item> + <Item Name="[{getKey(iSpan, 94)}]" Condition="getOffset(iSpan, 94) != 255">getNode(iSpan, 94)</Item> + <Item Name="[{getKey(iSpan, 95)}]" Condition="getOffset(iSpan, 95) != 255">getNode(iSpan, 95)</Item> + <Item Name="[{getKey(iSpan, 96)}]" Condition="getOffset(iSpan, 96) != 255">getNode(iSpan, 96)</Item> + <Item Name="[{getKey(iSpan, 97)}]" Condition="getOffset(iSpan, 97) != 255">getNode(iSpan, 97)</Item> + <Item Name="[{getKey(iSpan, 98)}]" Condition="getOffset(iSpan, 98) != 255">getNode(iSpan, 98)</Item> + <Item Name="[{getKey(iSpan, 99)}]" Condition="getOffset(iSpan, 99) != 255">getNode(iSpan, 99)</Item> + <Item Name="[{getKey(iSpan, 100)}]" Condition="getOffset(iSpan, 100) != 255">getNode(iSpan, 100)</Item> + <Item Name="[{getKey(iSpan, 101)}]" Condition="getOffset(iSpan, 101) != 255">getNode(iSpan, 101)</Item> + <Item Name="[{getKey(iSpan, 102)}]" Condition="getOffset(iSpan, 102) != 255">getNode(iSpan, 102)</Item> + <Item Name="[{getKey(iSpan, 103)}]" Condition="getOffset(iSpan, 103) != 255">getNode(iSpan, 103)</Item> + <Item Name="[{getKey(iSpan, 104)}]" Condition="getOffset(iSpan, 104) != 255">getNode(iSpan, 104)</Item> + <Item Name="[{getKey(iSpan, 105)}]" Condition="getOffset(iSpan, 105) != 255">getNode(iSpan, 105)</Item> + <Item Name="[{getKey(iSpan, 106)}]" Condition="getOffset(iSpan, 106) != 255">getNode(iSpan, 106)</Item> + <Item Name="[{getKey(iSpan, 107)}]" Condition="getOffset(iSpan, 107) != 255">getNode(iSpan, 107)</Item> + <Item Name="[{getKey(iSpan, 108)}]" Condition="getOffset(iSpan, 108) != 255">getNode(iSpan, 108)</Item> + <Item Name="[{getKey(iSpan, 109)}]" Condition="getOffset(iSpan, 109) != 255">getNode(iSpan, 109)</Item> + <Item Name="[{getKey(iSpan, 110)}]" Condition="getOffset(iSpan, 110) != 255">getNode(iSpan, 110)</Item> + <Item Name="[{getKey(iSpan, 111)}]" Condition="getOffset(iSpan, 111) != 255">getNode(iSpan, 111)</Item> + <Item Name="[{getKey(iSpan, 112)}]" Condition="getOffset(iSpan, 112) != 255">getNode(iSpan, 112)</Item> + <Item Name="[{getKey(iSpan, 113)}]" Condition="getOffset(iSpan, 113) != 255">getNode(iSpan, 113)</Item> + <Item Name="[{getKey(iSpan, 114)}]" Condition="getOffset(iSpan, 114) != 255">getNode(iSpan, 114)</Item> + <Item Name="[{getKey(iSpan, 115)}]" Condition="getOffset(iSpan, 115) != 255">getNode(iSpan, 115)</Item> + <Item Name="[{getKey(iSpan, 116)}]" Condition="getOffset(iSpan, 116) != 255">getNode(iSpan, 116)</Item> + <Item Name="[{getKey(iSpan, 117)}]" Condition="getOffset(iSpan, 117) != 255">getNode(iSpan, 117)</Item> + <Item Name="[{getKey(iSpan, 118)}]" Condition="getOffset(iSpan, 118) != 255">getNode(iSpan, 118)</Item> + <Item Name="[{getKey(iSpan, 119)}]" Condition="getOffset(iSpan, 119) != 255">getNode(iSpan, 119)</Item> + <Item Name="[{getKey(iSpan, 120)}]" Condition="getOffset(iSpan, 120) != 255">getNode(iSpan, 120)</Item> + <Item Name="[{getKey(iSpan, 121)}]" Condition="getOffset(iSpan, 121) != 255">getNode(iSpan, 121)</Item> + <Item Name="[{getKey(iSpan, 122)}]" Condition="getOffset(iSpan, 122) != 255">getNode(iSpan, 122)</Item> + <Item Name="[{getKey(iSpan, 123)}]" Condition="getOffset(iSpan, 123) != 255">getNode(iSpan, 123)</Item> + <Item Name="[{getKey(iSpan, 124)}]" Condition="getOffset(iSpan, 124) != 255">getNode(iSpan, 124)</Item> + <Item Name="[{getKey(iSpan, 125)}]" Condition="getOffset(iSpan, 125) != 255">getNode(iSpan, 125)</Item> + <Item Name="[{getKey(iSpan, 126)}]" Condition="getOffset(iSpan, 126) != 255">getNode(iSpan, 126)</Item> + <Item Name="[{getKey(iSpan, 127)}]" Condition="getOffset(iSpan, 127) != 255">getNode(iSpan, 127)</Item> + <Exec>iSpan++</Exec> + </If> + </Loop> + </CustomListItems> + </Expand> + </Type> + + <Type Name="QSet<*>"> + <DisplayString>{{ size={q_hash.d->size} }}</DisplayString> + <Expand> + <ExpandedItem>q_hash</ExpandedItem> + </Expand> + </Type> + + <Type Name="QVariant"> + <Intrinsic Name="typeId" Expression="*(int*)(&((const QtPrivate::QMetaTypeInterface *)(d.packedType << 2))->typeId)"> + </Intrinsic> + <Intrinsic Name="dataStar" Expression="(&(d.data.data))"> + </Intrinsic> + <Intrinsic Name="sharedDataStar" Expression="(d.is_shared ? reinterpret_cast<const void *>((size_t)(d.data.shared) + d.data.shared->offset) : (&(d.data.data)))"> + </Intrinsic> + + <DisplayString Condition="d.is_null">(null)</DisplayString> + + <!-- Static core pointers --> + <DisplayString Condition="typeId() == QMetaType::QObjectStar">QObject*</DisplayString> + + <!-- Static core template classes --> + <DisplayString Condition="typeId() == QMetaType::QVariantMap">{*(QMap<QString,QVariant>*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVariantList">{*(QList<QVariant>*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVariantHash">{*(QHash<QString,QVariant>*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVariantPair">QVariantPair</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QByteArrayList">{*(QList<QByteArray>*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QStringList">{*(QList<QString>*) sharedDataStar()}</DisplayString> + + <!-- Static primitives--> + <DisplayString Condition="typeId() == QMetaType::Bool">{*(bool*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Int">{*(int*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::UInt">{*(unsigned int*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::LongLong">{*(long long*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::ULongLong">{*(unsigned long long*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Double">{*(double*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::VoidStar">{*(void**) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Long">{*(long*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Short">{*(short*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Char">{*(char*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Char16">{*(char16_t*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Char32">{*(char32_t*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::ULong">{*(unsigned long*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::UShort">{*(unsigned short*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::UChar">{*(unsigned char*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::Float">{*(float*) dataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::SChar">{*(signed char*) dataStar()}</DisplayString> + + <!-- Static core classes --> + <DisplayString Condition="typeId() == QMetaType::QChar">{*(QChar*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QString">{*(QString*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QByteArray">{*(QByteArray*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QDate">{*(QDate*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QTime">{*(QTime*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QDateTime">QDateTime</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QUrl">QUrl</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QLocale">QLocale</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QRect">{*(QRect*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QRectF">{*(QRectF*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QSize">{*(QSize*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QSizeF">{*(QSizeF*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QLine">{*(QLine*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QLineF">{*(QLineF*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPoint">{*(QPoint*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPointF">{*(QPointF*) sharedDataStar()}</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QEasingCurve">EasingCurve</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QUuid">Uuid</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QRegularExpression">RegularExpression</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QJsonValue">QJsonValue</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QJsonObject">QJsonObject</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QJsonArray">QJsonArray</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QJsonDocument">QJsonDocument</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QCborValue">QCborValue</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QCborArray">QCborArray</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QCborMap">QCborMap</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QModelIndex">ModelIndex</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPersistentModelIndex">QPersistentModelIndex</DisplayString> + + <!-- Static gui classes --> + <DisplayString Condition="typeId() == QMetaType::QFont">QFont</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPixmap">QPixmap</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QBrush">QBrush</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QColor">QColor</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPalette">QPalette</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QIcon">QIcon</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QImage">QImage</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPolygon">QPolygon</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QRegion">QRegion</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QBitmap">QBitmap</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QCursor">QCursor</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QKeySequence">QKeySequence</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPen">QPen</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QTextLength">QTextLength</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QTextFormat">QTextFormat</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QTransform">QTransform</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QMatrix4x4">QMatrix4x4</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVector2D">QVector2D</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVector3D">QVector3D</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QVector4D">QVector4D</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QQuaternion">QQuaternion</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QPolygonF">QPolygonF</DisplayString> + <DisplayString Condition="typeId() == QMetaType::QColorSpace">QColorSpace</DisplayString> + + <!-- Static widget classes --> + <DisplayString Condition="typeId() == QMetaType::QSizePolicy">QSizePolicy</DisplayString> + + <!-- Unhandled : display the typeId--> + <DisplayString>QMetaType::Type ({typeId()})</DisplayString> + + <Expand> + <ExpandedItem Condition="typeId() == QMetaType::QString">*(QString*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QByteArray">*(QByteArray*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QDate">*(QDate*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QTime">*(QTime*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QRect">*(QRect*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QRectF">*(QRectF*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QSize">*(QSize*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QSizeF">*(QSizeF*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QLine">*(QLine*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QLineF">*(QLineF*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QPoint">*(QPoint*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QPointF">*(QPointF*) sharedDataStar()</ExpandedItem> + + <ExpandedItem Condition="typeId() == QMetaType::QVariantMap">*(QMap<QString,QVariant>*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QVariantList">*(QList<QVariant>*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QVariantHash">*(QHash<QString,QVariant>*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QByteArrayList">*(QList<QByteArray>*) sharedDataStar()</ExpandedItem> + <ExpandedItem Condition="typeId() == QMetaType::QStringList">*(QList<QString>*) sharedDataStar()</ExpandedItem> + </Expand> + </Type> + +</AutoVisualizer>