From af258785dc38258444b841db17c4cf8eb619ba40 Mon Sep 17 00:00:00 2001 From: taynpg Date: Tue, 28 May 2024 15:46:58 +0800 Subject: [PATCH] =?UTF-8?q?ver=EF=BC=9Av1.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 88 ++- CMakeLists.txt | 7 +- main.cpp | 410 +++++++++++- src/pub.cpp | 84 +++ src/pub.h | 22 + template/.clang-format | 38 ++ template/console/CMakeLists.txt | 14 + template/console/main.cpp | 7 + template/qt-console/CMakeLists.txt | 26 + template/qt-console/main.cpp | 8 + template/qt-printer/.gdbinit | 7 + template/qt-printer/QtPrinters/helper.py | 80 +++ template/qt-printer/QtPrinters/qt.py | 776 +++++++++++++++++++++ template/qt-widget/CMakeLists.txt | 74 +++ template/qt-widget/main.cpp | 11 + template/qt-widget/mainwidget.cpp | 14 + template/qt-widget/mainwidget.h | 23 + template/qt-widget/mainwidget.ui | 19 + template/qt5.natvis | 814 +++++++++++++++++++++++ template/qt6.natvis | 735 ++++++++++++++++++++ 20 files changed, 3242 insertions(+), 15 deletions(-) create mode 100644 src/pub.cpp create mode 100644 src/pub.h create mode 100644 template/.clang-format create mode 100644 template/console/CMakeLists.txt create mode 100644 template/console/main.cpp create mode 100644 template/qt-console/CMakeLists.txt create mode 100644 template/qt-console/main.cpp create mode 100644 template/qt-printer/.gdbinit create mode 100644 template/qt-printer/QtPrinters/helper.py create mode 100644 template/qt-printer/QtPrinters/qt.py create mode 100644 template/qt-widget/CMakeLists.txt create mode 100644 template/qt-widget/main.cpp create mode 100644 template/qt-widget/mainwidget.cpp create mode 100644 template/qt-widget/mainwidget.h create mode 100644 template/qt-widget/mainwidget.ui create mode 100644 template/qt5.natvis create mode 100644 template/qt6.natvis 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 -#include -#include #include +#include +#include +#include +#include +#include #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(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 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(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 + +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(file)), (std::istreambuf_iterator())); + 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 +#include + + +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 + +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 + +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 +# +# 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 +# +# 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::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'] + #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(%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 "" + # 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(%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 + +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 + +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 @@ + + + MainWidget + + + + 0 + 0 + 800 + 600 + + + + MainWidget + + + + + 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 @@ + + + + + + + {{{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}}} + + + + + {{ x = {xp}, y = {yp} }} + + xp + yp + + + + + {{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }} + + x1 + y1 + x2 - x1 + 1 + y2 - y1 + 1 + + + + + {{ x = {xp}, y = {yp}, width = {w}, height = {h} }} + + xp + yp + w + h + + + + + + {{ width = {wd}, height = {ht} }} + + wd + ht + + + + + + {{ start point = {pt1}, end point = {pt2} }} + + + {pt1} + + pt1 + + + + {pt2} + + pt2 + + + + + + + + {{ size = {d->size} }} + + d->ref.atomic._q_value + + d->size + (QPoint*)((reinterpret_cast<char*>(d)) + d->offset) + + + + + + {{ size = {d->size} }} + + + 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) + + d->ref.atomic._q_value + + d->size + (QPointF*)((reinterpret_cast<char*>(d)) + d->offset) + + + + + + {{ x = {xp}, y = {yp} }} + + xp + yp + + + + + {{ x = {xp}, y = {yp}, z = {zp} }} + + xp + yp + zp + + + + + {{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }} + + xp + yp + zp + wp + + + + + + {{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }} + + + _m11 + _m12 + _m21 + _m22 + _dx + _dy + + + + + + {{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }} + + + m[0][0] + m[1][0] + m[2][0] + m[3][0] + m[0][1] + m[1][1] + m[2][1] + m[3][1] + m[0][2] + m[1][2] + m[2][2] + m[3][2] + m[0][3] + m[1][3] + m[2][3] + m[3][3] + + + + + + {{ horizontal = {static_cast<Policy>(bits.horPolicy)}, vertical = {static_cast<Policy>(bits.verPolicy)}, type = {ControlType(1 << bits.ctype)} }} + + + + QSizePolicy::Policy::{static_cast<Policy>(bits.verPolicy)} + + + QSizePolicy::Policy::{static_cast<Policy>(bits.horPolicy)} + + + QSizePolicy::ControlType::{ControlType(1 << bits.ctype)} + + + + Qt::Vertical (2) + + + Qt::Horizontal (1) + + + static_cast<int>(bits.verStretch) + static_cast<int>(bits.horStretch) + bits.hfw == 1 + bits.wfh == 1 + + + + + {ucs,c} + ucs,c + + ucs > 0xff ? '\0' : char(ucs),c + ucs,c + + + + + {((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub} + ((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),sub + + d->size + d->ref.atomic._q_value + + d->size + ((reinterpret_cast<unsigned short*>(d)) + d->offset / 2),c + + + + + + + {m_string,[m_size]} u"" + {offset() + m_position,[m_size]} + + m_position + m_size + + m_size + offset()+m_position + + + + + + {m_data,[m_size]} + m_data,[m_size] + + m_size + + m_size + m_data + + + + + + {((reinterpret_cast<char*>(d)) + d->offset),sb} + ((reinterpret_cast<char*>(d)) + d->offset),sb + + d->size + d->ref.atomic._q_value + + d->size + ((reinterpret_cast<char*>(d)) + d->offset),c + + + + + + + + + + + + + + + + + + + + {scheme()}://{host()}{path()} + {path()} + + scheme() + username() + password() + host() + path() + query() + fragment() + + + + + {{ size = {(d.d->size << 3) - *((reinterpret_cast<char*>(d.d)) + d.d->offset)} }} + + d.d->ref.atomic._q_value + + (d.d->size << 3) - *((reinterpret_cast<char*>(d.d)) + d.d->offset) + + (*(reinterpret_cast<const unsigned char*>((reinterpret_cast<char*>(d.d)) + d.d->offset) + 1 + + ($i >> 3)) & (1 << ($i & 7))) != 0 + + + + + + + + {{ size = {s} }} + + a + + s + ptr + + + + + + {{ julian day = {jd} }} + + + + + {{ millisecond = {mds} }} + {{ milliseconds = {mds} }} + + mds / 3600000, d + mds / 3600000, d + (mds % 3600000) / 60000, d + (mds % 3600000) / 60000, d + (mds / 1000) % 60, d + (mds / 1000) % 60, d + mds % 1000, d + mds % 1000, d + + + + + {d.pattern} + + + + + ref._q_value + + + + + strong reference to shared pointer of type {"$T1"} + + value == 0 + d->weakref._q_value + d->strongref._q_value + + + + + pointer to implicit shared object of type {"$T1"} + + d + + + + + pointer to explicit shared object of type {"$T1"} + + d + + + + + guarded pointer to subclass of QObject of type {"$T1"} + + wp.d == 0 || wp.d->strongref._q_value == 0 || wp.value == 0 + + + + + weak reference to shared pointer of type {"$T1"} + + d == 0 || d->strongref._q_value == 0 || value == 0 + d->weakref._q_value + d->strongref._q_value + + + + + scoped pointer to a dynamically allocated object of type {"$T1"} + + !d + + + + + scoped pointer to dynamically allocated array of objects of type {"$T1"} + + !d + + + + + ({first}, {second}) + + first + second + + + + + + {{ size = {d->size} }} + + d->ref.atomic._q_value + + d->size + ($T1*)((reinterpret_cast<char*>(d)) + d->offset) + + + + + + + {{ size = {d->end - d->begin} }} + + d->ref.atomic._q_value + + d->end - d->begin + *reinterpret_cast<$T1*>((sizeof($T1) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<$T1*>(d->array + d->begin + $i)) + + + + + + + {{ size = {d->end - d->begin} }} + + d->ref.atomic._q_value + + d->end - d->begin + + *reinterpret_cast<QString*>((sizeof(QString) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QString*>(d->array + d->begin + $i)) + + + + + + + {{ size = {d->end - d->begin} }} + + d->ref.atomic._q_value + + d->end - d->begin + + *reinterpret_cast<QVariant*>((sizeof(QVariant) > sizeof(void*)) + ? reinterpret_cast<Node*>(d->array + d->begin + $i)->v + : reinterpret_cast<QVariant*>(d->array + d->begin + $i)) + + + + + + + {{ size = {d->size} }} + + d->ref.atomic._q_value + + d->size + d->n + n + (*(QLinkedListNode<$T1>*)this).t + + + + + + ({key}, {value}) + + key + value + + + + + + {{ size = {d->size} }} + + d->ref.atomic._q_value + + d->size + d->header.left + left + right + *((QMapNode<$T1,$T2>*)this) + + + + + + (empty) + ({key}, {value}) + + key + value + next + + + + + + {{ size = {d->size} }} + + + d->numBuckets + reinterpret_cast<Node **>(d->buckets) + + + + + + + d->size + + + node = *(bucket++) + --n + + + keyValuePair = reinterpret_cast<Node *>(node) + keyValuePair->value + node = node->next + + + + + + + + (empty) + ({key}) + + key + + + + + {{ size = {q_hash.d->size} }} + + q_hash + + + + + ({*keyPtr}, {*t}) + + *keyPtr + *t + + + + + {{ size = {hash.d->size} }} + + mx + total + hash.d->ref.atomic._q_value + + hash.d->size + f + n + *((Node*)this) + + + + + + + + + + + + + + {{ row count = {(*d_ptr.d).rows()}, column count = {(*d_ptr.d).columns()} }} + + d_ptr.d,! + (*d_ptr.d).rows() + (*d_ptr.d).columns() + + + + + + + Invalid + {d.data.b} + {d.data.i} + {d.data.u} + {d.data.ll} + {d.data.ull} + {d.data.d} + {d.data.c} + + {*((QMap<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QList<QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QStringList*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QBitArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QDate*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QTime*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + DateTime + Url + Locale + + {*((QRect*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QRectF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QSize*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QSizeF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QLine*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QLineF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QPoint*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + + {*((QPointF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + RegExp + RegularExpression + + {*((QHash<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr)))} + + EasingCurve + Uuid + ModelIndex + LastCoreType + Font + Pixmap + Brush + Color + Palette + Image + Polygon + Region + Bitmap + Cursor + KeySequence + Pen + TextLength + TextFormat + Matrix + Transform + Matrix4x4 + Vector2D + Vector3D + Vector4D + Quaternion + PolygonF + Icon + LastGuiType + SizePolicy + UserType + LastType + + + + + + d.data.c + + + *((QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + + *((QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + + + + + + + *((QMap<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QList<QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QString*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QStringList*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QByteArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QBitArray*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QDate*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QTime*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QRect*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QRectF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QSize*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QSizeF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QLine*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QLineF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QPoint*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QPointF*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + *((QHash<QString,QVariant>*)(d.is_shared ? d.data.shared->ptr + : reinterpret_cast<const void *>(&d.data.ptr))) + + + + + + + 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 @@ + + + + + + + {val} + + val + + + + + + + + {{ x = {x,g}, y = {y,g}, z = {_extraData().z,g}, width = {width,g}, height = {height,g} }} + {{ x = {x,g}, y = {y,g}, width = {width,g}, height = {height,g} }} + + x + y + _extraData().z + _extraData().scale + _extraData().rotation + _extraData().opacity + width + height + implicitWidth + implicitHeight + effectiveVisible + explicitEnable + _objectName(),na + parentItem + childItems, nr + + + + + {d_ptr.d,na} + + d_ptr.d + + + + + {{{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}}} + + + + {val} + + val + + + + + {_q_value} + + _q_value + + + + + + + empty + {_q_value} + + *value() + + + + + + {{ x = {xp}, y = {yp} }} + + xp + yp + + + + + {{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }} + + x1 + y1 + x2 - x1 + 1 + y2 - y1 + 1 + + + + + {{ x = {xp}, y = {yp}, width = {w}, height = {h} }} + + xp + yp + w + h + + + + + + {{ width = {wd}, height = {ht} }} + + wd + ht + + + + + + {{ start point = {pt1}, end point = {pt2} }} + + + {pt1} + + pt1 + + + + {pt2} + + pt2 + + + + + + + + {{ size={d->size} }} + + d->ref.atomic._q_value + + d->size + (QPoint*)((reinterpret_cast<char*>(d)) + d->offset) + + + + + + {{ size={d->size} }} + + + 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) + + d->ref.atomic._q_value + + d->size + (QPointF*)((reinterpret_cast<char*>(d)) + d->offset) + + + + + + {{ x = {xp}, y = {yp} }} + + xp + yp + + + + + {{ x = {xp}, y = {yp}, z = {zp} }} + + xp + yp + zp + + + + + {{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }} + + xp + yp + zp + wp + + + + + + {{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }} + + + _m11 + _m12 + _m21 + _m22 + _dx + _dy + + + + + + {{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }} + + + m[0][0] + m[1][0] + m[2][0] + m[3][0] + m[0][1] + m[1][1] + m[2][1] + m[3][1] + m[0][2] + m[1][2] + m[2][2] + m[3][2] + m[0][3] + m[1][3] + m[2][3] + m[3][3] + + + + + + {{ horizontal = {static_cast<Policy>(bits.horPolicy)}, vertical = {static_cast<Policy>(bits.verPolicy)}, type = {ControlType(1 << bits.ctype)} }} + + + + QSizePolicy::Policy::{static_cast<Policy>(bits.verPolicy)} + + + QSizePolicy::Policy::{static_cast<Policy>(bits.horPolicy)} + + + QSizePolicy::ControlType::{ControlType(1 << bits.ctype)} + + + + Qt::Vertical (2) + + + Qt::Horizontal (1) + + + static_cast<int>(bits.verStretch) + static_cast<int>(bits.horStretch) + bits.hfw == 1 + bits.wfh == 1 + + + + + {ucs,c} + ucs,c + + ucs > 0xff ? '\0' : char(ucs),c + ucs,c + + + + + "{(reinterpret_cast<unsigned short*>(d.ptr)),sub}" + (reinterpret_cast<unsigned short*>(d.ptr)),sub + + d.size + + d.size + d.ptr + + + + + + {m_string,[m_size]} u"" + {m_string->d.ptr+m_position,[m_size]} + "" + m_string,[m_position+m_size] + + m_position + m_size + + m_size + m_string->d.ptr+m_position + + + + + + {m_data,[m_size]} + m_data,[m_size] + + m_size + + m_size + m_data + + + + + + "{((reinterpret_cast<char*>(d.ptr))),sb}" + ((reinterpret_cast<char*>(d.ptr))),sb + + d.size + + d.size + d.ptr + + + + + + + + + + + + + + + + + + + + {scheme()}://{host()}{path()} + {path()} + + scheme() + username() + password() + host() + path() + query() + fragment() + + + + + {{ julian day = {jd} }} + + + + + + + + {{ millisecond = {mds} }} + {{ milliseconds = {mds} }} + + hour(), d + hour(), d + minute(), d + minute(), d + second(), d + second(), d + millisecond(), d + millisecond(), d + + + + + ({first}, {second}) + + first + second + + + + + + {{ size={d.size} }} + + + d.size + reinterpret_cast<$T1*>(d.ptr) + + + + + + {{ size={s} }} + + a + + s + ptr + + + + + + + {{ size={d.d->m._Mypair._Myval2._Myval2._Mysize} }} + + + d.d->m._Mypair._Myval2._Myval2._Mysize + d.d->m._Mypair._Myval2._Myval2._Myhead->_Parent + _Left + _Right + _Myval,view(MapHelper) + + + + + + {second} + + + + {value} + + key + value + + + + + {value->value} + ({value->value}, {value->next->value}) + ({value->value}, {value->next->value}, ...) + + + value + next + value + + + + + + + + + + + + + + + + + + + + {{ size={d->size} }} + + + + + d->size + + + getNode(iSpan, 0) + getNode(iSpan, 1) + getNode(iSpan, 2) + getNode(iSpan, 3) + getNode(iSpan, 4) + getNode(iSpan, 5) + getNode(iSpan, 6) + getNode(iSpan, 7) + getNode(iSpan, 8) + getNode(iSpan, 9) + getNode(iSpan, 10) + getNode(iSpan, 11) + getNode(iSpan, 12) + getNode(iSpan, 13) + getNode(iSpan, 14) + getNode(iSpan, 15) + getNode(iSpan, 16) + getNode(iSpan, 17) + getNode(iSpan, 18) + getNode(iSpan, 19) + getNode(iSpan, 20) + getNode(iSpan, 21) + getNode(iSpan, 22) + getNode(iSpan, 23) + getNode(iSpan, 24) + getNode(iSpan, 25) + getNode(iSpan, 26) + getNode(iSpan, 27) + getNode(iSpan, 28) + getNode(iSpan, 29) + getNode(iSpan, 30) + getNode(iSpan, 31) + getNode(iSpan, 32) + getNode(iSpan, 33) + getNode(iSpan, 34) + getNode(iSpan, 35) + getNode(iSpan, 36) + getNode(iSpan, 37) + getNode(iSpan, 38) + getNode(iSpan, 39) + getNode(iSpan, 40) + getNode(iSpan, 41) + getNode(iSpan, 42) + getNode(iSpan, 43) + getNode(iSpan, 44) + getNode(iSpan, 45) + getNode(iSpan, 46) + getNode(iSpan, 47) + getNode(iSpan, 48) + getNode(iSpan, 49) + getNode(iSpan, 50) + getNode(iSpan, 51) + getNode(iSpan, 52) + getNode(iSpan, 53) + getNode(iSpan, 54) + getNode(iSpan, 55) + getNode(iSpan, 56) + getNode(iSpan, 57) + getNode(iSpan, 58) + getNode(iSpan, 59) + getNode(iSpan, 60) + getNode(iSpan, 61) + getNode(iSpan, 62) + getNode(iSpan, 63) + getNode(iSpan, 64) + getNode(iSpan, 65) + getNode(iSpan, 66) + getNode(iSpan, 67) + getNode(iSpan, 68) + getNode(iSpan, 69) + getNode(iSpan, 70) + getNode(iSpan, 71) + getNode(iSpan, 72) + getNode(iSpan, 73) + getNode(iSpan, 74) + getNode(iSpan, 75) + getNode(iSpan, 76) + getNode(iSpan, 77) + getNode(iSpan, 78) + getNode(iSpan, 79) + getNode(iSpan, 80) + getNode(iSpan, 81) + getNode(iSpan, 82) + getNode(iSpan, 83) + getNode(iSpan, 84) + getNode(iSpan, 85) + getNode(iSpan, 86) + getNode(iSpan, 87) + getNode(iSpan, 88) + getNode(iSpan, 89) + getNode(iSpan, 90) + getNode(iSpan, 91) + getNode(iSpan, 92) + getNode(iSpan, 93) + getNode(iSpan, 94) + getNode(iSpan, 95) + getNode(iSpan, 96) + getNode(iSpan, 97) + getNode(iSpan, 98) + getNode(iSpan, 99) + getNode(iSpan, 100) + getNode(iSpan, 101) + getNode(iSpan, 102) + getNode(iSpan, 103) + getNode(iSpan, 104) + getNode(iSpan, 105) + getNode(iSpan, 106) + getNode(iSpan, 107) + getNode(iSpan, 108) + getNode(iSpan, 109) + getNode(iSpan, 110) + getNode(iSpan, 111) + getNode(iSpan, 112) + getNode(iSpan, 113) + getNode(iSpan, 114) + getNode(iSpan, 115) + getNode(iSpan, 116) + getNode(iSpan, 117) + getNode(iSpan, 118) + getNode(iSpan, 119) + getNode(iSpan, 120) + getNode(iSpan, 121) + getNode(iSpan, 122) + getNode(iSpan, 123) + getNode(iSpan, 124) + getNode(iSpan, 125) + getNode(iSpan, 126) + getNode(iSpan, 127) + iSpan++ + + + + + + + + {{ size={q_hash.d->size} }} + + q_hash + + + + + + + + + + + + (null) + + + QObject* + + + {*(QMap<QString,QVariant>*) sharedDataStar()} + {*(QList<QVariant>*) sharedDataStar()} + {*(QHash<QString,QVariant>*) sharedDataStar()} + QVariantPair + {*(QList<QByteArray>*) sharedDataStar()} + {*(QList<QString>*) sharedDataStar()} + + + {*(bool*) dataStar()} + {*(int*) dataStar()} + {*(unsigned int*) dataStar()} + {*(long long*) dataStar()} + {*(unsigned long long*) dataStar()} + {*(double*) dataStar()} + {*(void**) dataStar()} + {*(long*) dataStar()} + {*(short*) dataStar()} + {*(char*) dataStar()} + {*(char16_t*) dataStar()} + {*(char32_t*) dataStar()} + {*(unsigned long*) dataStar()} + {*(unsigned short*) dataStar()} + {*(unsigned char*) dataStar()} + {*(float*) dataStar()} + {*(signed char*) dataStar()} + + + {*(QChar*) sharedDataStar()} + {*(QString*) sharedDataStar()} + {*(QByteArray*) sharedDataStar()} + {*(QDate*) sharedDataStar()} + {*(QTime*) sharedDataStar()} + QDateTime + QUrl + QLocale + {*(QRect*) sharedDataStar()} + {*(QRectF*) sharedDataStar()} + {*(QSize*) sharedDataStar()} + {*(QSizeF*) sharedDataStar()} + {*(QLine*) sharedDataStar()} + {*(QLineF*) sharedDataStar()} + {*(QPoint*) sharedDataStar()} + {*(QPointF*) sharedDataStar()} + EasingCurve + Uuid + RegularExpression + QJsonValue + QJsonObject + QJsonArray + QJsonDocument + QCborValue + QCborArray + QCborMap + ModelIndex + QPersistentModelIndex + + + QFont + QPixmap + QBrush + QColor + QPalette + QIcon + QImage + QPolygon + QRegion + QBitmap + QCursor + QKeySequence + QPen + QTextLength + QTextFormat + QTransform + QMatrix4x4 + QVector2D + QVector3D + QVector4D + QQuaternion + QPolygonF + QColorSpace + + + QSizePolicy + + + QMetaType::Type ({typeId()}) + + + *(QString*) sharedDataStar() + *(QByteArray*) sharedDataStar() + *(QDate*) sharedDataStar() + *(QTime*) sharedDataStar() + *(QRect*) sharedDataStar() + *(QRectF*) sharedDataStar() + *(QSize*) sharedDataStar() + *(QSizeF*) sharedDataStar() + *(QLine*) sharedDataStar() + *(QLineF*) sharedDataStar() + *(QPoint*) sharedDataStar() + *(QPointF*) sharedDataStar() + + *(QMap<QString,QVariant>*) sharedDataStar() + *(QList<QVariant>*) sharedDataStar() + *(QHash<QString,QVariant>*) sharedDataStar() + *(QList<QByteArray>*) sharedDataStar() + *(QList<QString>*) sharedDataStar() + + + +