精华内容
下载资源
问答
  • 一、QtCreator简介 QtCreator是设计精巧的插件式系统,QtCreator的核心是一个插件管理器,其所有功能都是使用插件完成。...针对QtCreator的插件机制设计,QtCreator源码分析会将关注重点放在插件管

    一、QtCreator简介

    QtCreator是设计精巧的插件式系统,QtCreator的核心是一个插件管理器,其所有功能都是使用插件完成。在启动时,QtCreator会首先加载一个名为coreplugin的插件,coreplugin插件提供了Qt Creator最基本的功能和扩展点,其余的插件都是直接或间接依赖于coreplugin插件提供的机制,一步步扩充QtCreator的功能,最终将其变成一个功能完整的IDE。
    针对QtCreator的插件机制设计,QtCreator源码分析会将关注重点放在插件管理器的实现、coreplugin的实现上面。QtCreator完全基于qmake的复杂开发模式,需要学会如何使用qmake管理一个相当复杂的项目(QtCreator近5000个文件),如何开发自定义插件管理器,如何使用插件扩展定制系统等。

    二、QtCreator源码简介

    1、QtCreator源码目录简介

    QtCreator-2.8.1包含5000多个文件,代码行数超过了110万行。
    源码目录如下:
    QtCreator源码分析(一)——QtCreator源码简介![]
    bin: 生成Linux平台shell脚本。
    dist: 安装文件配置信息和版本更新记录。
    doc: 生成doxygen文档的配置文件。
    lib:Qt组件相关的QML文件
    qbs:QBS 配置文件。QBS,即 Qt Build Suite,是一种跨平台的编译工具,目的是将高层的项目描述(使用类似QML的语言)转换成底层的编译描述(供 make 等工具使用的信息)。它可以简化多平台的编译过程。QBS与qmake类似,区别在于前者适用于任意项目,而后者一般仅供Qt项目使用。在阅读代码时将关注 qmake,不会深入研究QBS的使用。
    scripts: QtCreator使用的perl以及python等脚本。
    share: 源代码中所需要的一些非代码共享文件,例如代码模板等。
    src: QtCreator源代码文件。
    tests: QtCreator测试代码。
    HACKING: QtCreator编码规范。
    LICENSE.LGPL: LGPL协议。
    qtcreator.pri: QtCreator项目需要使用的通用配置,一般会被include到大部分 pro文件。
    qtcreator.pro: QtCreator的qmake项目文件。
    qtcreator.qbs:  Qt Creator 的 QBS 项目文件。
    README: 有关如何编译QtCreator等相关事宜的一些说明。
    .gitignore: git忽略文件配置。
    .gitmodules:git 子模块配置

    2、QtCreator源码编译

    Linux环境下直接使用QtCreator-2.8.1+Qt4.8.6编译
    运行结果如下:
    QtCreator源码分析(一)——QtCreator源码简介

    三、QtCreator简介

    QtCreator主要由主窗口区、菜单栏、模式选择器、常用按钮、定位器、输出面板等组成。

    1、QtCreator菜单栏

    QtCreator菜单栏包含文件、编辑、构建、调试、分析、工具、窗体、帮助八个菜单选项。
    文件菜单包含新建、打开、关闭项目和文件,打印文件和退出等基本功能菜单。
    编辑菜单包含撤销、剪切、复制、查找等常用功能,高级菜单包含标示空白符、折叠代码、改变字体大小等功能。
    构建菜单包含构件和运行项目等相关菜单。
    调试菜单包含调试程序相关的功能菜单。
    分析菜单包含常用分析工具的菜单。
    工具菜单包含快速定位菜单、版本控制工具菜单、界面编辑器菜单等。
    窗体菜单包含设置窗口布局的一些菜单,如全局显示、隐藏边栏。
    帮助菜单包含Qt帮助、QtCreator版本信息和插件管理等菜单。

    2、QtCreator模式选择器

    QtCreator模式选择器包括欢迎模式、编辑模式、设计器模式、调试模式、项目模式、分析模式、帮助模式。
    欢迎模式主要提供一些功能的快捷入口,如打开帮助教程、打开示例程序、打开项目、新建项目、快速打开以前的项目和会话等功能
    编辑模式主要提供查看和编辑程序代码,管理项目文件等功能。QtCreator编辑器具有关键字特殊颜色显示、代码自动补全、声明定义间快捷切换、函数原型提示、F1键快速打开相关帮助、全项目中进行查找等功能。
    设计器模式整合了Qt Designer的功能,设计图形界面,进行部件属性设置、信号和槽设置、布局设置等。
    调试模式,QtCreator默认使用GDB进行调试,支持设置断点、单步调试和远程调试等功能,包含局部变量和监视器、断点、线程、快照查看窗口等。
    项目模式,包含具体项目的构建设置、运行设置、编辑器设置、依赖关系等页面。构建设置中可以对项目的版本、使用的Qt版本、编译步骤进行设置。编辑器设置中可以设置文件的默认编码。
    帮助模式,整合了Qt助手,包含目录、查找、索引、书签等导航模式。

    3、QtCreator常用按钮

    QtCreator常用按钮包括目标选择器、运行按钮、调试按钮、构建按钮。目标选择器用来选择要构建哪个平台的项目;运行按钮实现项目的构建和运行;调试按钮进入调试模式,进行程序调试;构建按钮可以构建所有打开的项目。

    4、QtCreator定位器

    QtCreator中,定位器用来快速定位项目、文件、类、方法、帮助文档、文件系统,可以使用过滤器更加准确定位要查找的结果。

    5、QtCreator输出面板

    QtCreator输出面板包含了构建问题、搜索结果、应用程序输出、编译输出、QML/JS命令窗口、一般信息。
    构建问题窗口显示程序编译时的错误和警告信息;搜索结果窗口显示执行搜索后的结果信息;应用程序输出窗口显示在程序运行过程中输出的所有信息;编译输出窗口显示在程序编译过程中输出的相关信息;QML命令窗口显示QML命令记录;版本控制系统窗口显示版本控制系统的记录。

    展开全文
  • Qt Creator 插件开发/QtCreator源码分析

    千次阅读 2018-05-02 23:39:06
    项目开发采用了Qt的插件机制。大体上也参考了QtCreator和Lite...如果要分析QtCreator软件设计的一些思路,大概了解之后再去啃源码可能相对就会容易一点。仅供参考。 《Qt Creator 插件开发》目录 https://www....

    项目开发采用了Qt的插件机制。大体上也参考了QtCreator和LiteIDE这两个开源项目的插件管理及其他方面的一些内容。LiteIDE里部分内容及管理都参考了QtCreator。但LiteIDE网上找不到相关介绍的博文。如果要分析QtCreator软件设计的一些思路,大概了解之后再去啃源码可能相对就会容易一点。仅供参考。


    《Qt Creator 插件开发》目录
    https://www.devbean.net/2012/03/qtcreator-plugin-develop-catalog/


    QtCreator源码学习
    https://www.devbean.net/category/qt-creator-%E6%BA%90%E7%A0%81%E5%AD%A6%E4%B9%A0/

    展开全文
  • Qt Creator源码分析系列——HostOsInfo类

    千次阅读 2020-02-19 21:58:18
    该篇文章内容主要集中Qt Creator HostOsInfo部分代码的分析。从分析插件中的coreplugin中的HostOsInfo模块开始,项目文件在路径\qt-creator-master\qt-creator-master\src\utils\utils-lib\下。 从hostosinfo.h引入...

    该篇文章内容主要集中Qt Creator HostOsInfo部分代码的分析。从分析插件中的coreplugin中的HostOsInfo模块开始,项目文件在路径\qt-creator-master\qt-creator-master\src\utils\utils-lib\下。

    从hostosinfo.h引入的头文件看起:

    #include "utils_global.h"
    #include "osspecificaspects.h"
    #include <QString>
    

    utils_global.h内容如下所示,如果定义了UTILS_LIBRARY,则将QTCREATOR_UTILS_EXPORT定义为Q_DECL_EXPORT。如果定义了QTCREATOR_UTILS_STATIC_LIB,则将QTCREATOR_UTILS_EXPORT定义为空(单个文件进行手动测试)。否则,将QTCREATOR_UTILS_EXPORT定义为Q_DECL_IMPORT。只是用于设置编译输出方式的。

    #pragma once
    #include <qglobal.h>
    #if defined(UTILS_LIBRARY)
    #  define QTCREATOR_UTILS_EXPORT Q_DECL_EXPORT
    #elif  defined(QTCREATOR_UTILS_STATIC_LIB) // Abuse single files for manual tests
    #  define QTCREATOR_UTILS_EXPORT
    #else
    #  define QTCREATOR_UTILS_EXPORT Q_DECL_IMPORT
    #endif
    

    osspecificaspects.h

    因为是windows平台,这里QTC_WIN_EXE_SUFFIX定义为".exe"。Utils命名空间里有代表操作系统类型的枚举类型。

    #pragma once
    #include <QString>
    #include <algorithm>
    #define QTC_WIN_EXE_SUFFIX ".exe"
    namespace Utils {
    // Add more as needed.
    enum OsType { OsTypeWindows, OsTypeLinux, OsTypeMac, OsTypeOtherUnix, OsTypeOther };
    namespace OsSpecificAspects {
    // 如果操作系统类型是Windows,则在形参executable后加上后缀.exe
    inline QString withExecutableSuffix(OsType osType, const QString &executable)
    {
        QString finalName = executable;
        if (osType == OsTypeWindows)
            finalName += QLatin1String(QTC_WIN_EXE_SUFFIX);
        return finalName;
    }
    // 如果是Windows或者Mac平台则是Qt::CaseInsensitive(大小写不敏感)
    inline Qt::CaseSensitivity fileNameCaseSensitivity(OsType osType)
    {
        return osType == OsTypeWindows || osType == OsTypeMac ? Qt::CaseInsensitive : Qt::CaseSensitive;
    }
    inline Qt::CaseSensitivity envVarCaseSensitivity(OsType osType)
    {
        return fileNameCaseSensitivity(osType);
    }
    // 路径分隔符  windows平台是; 其它平台是:
    inline QChar pathListSeparator(OsType osType)
    {
        return QLatin1Char(osType == OsTypeWindows ? ';' : ':');
    }
    // 键盘修改器 如果是Mac平台,则是Qt::MetaModifier 其他是Qt::ControlModifier
    inline Qt::KeyboardModifier controlModifier(OsType osType)
    {
        return osType == OsTypeMac ? Qt::MetaModifier : Qt::ControlModifier;
    }
    // 将Windows下的pathName中的/都替换为\\
    inline QString pathWithNativeSeparators(OsType osType, const QString &pathName)
    {
        if (osType == OsTypeWindows) {
            const int pos = pathName.indexOf('/');
            if (pos >= 0) {
                QString n = pathName;
                std::replace(std::begin(n) + pos, std::end(n), '/', '\\');
                return n;
            }
        }
        return pathName;
    }
    } // namespace OsSpecificAspects
    } // namespace Utils
    

    HostOsInfo类

    HostOsInfo类包含了返回操作系统类型的hostOs函数、返回CPU架构的hostArchitecture函数

    namespace Utils {
    class QTCREATOR_UTILS_EXPORT HostOsInfo
    {
    public:
    	// 这里的OsType就是上面介绍的枚举类型
        static constexpr OsType hostOs()
        {
    #if defined(Q_OS_WIN)
            return OsTypeWindows;
    #elif defined(Q_OS_LINUX)
            return OsTypeLinux;
    #elif defined(Q_OS_MAC)
            return OsTypeMac;
    #elif defined(Q_OS_UNIX)
            return OsTypeOtherUnix;
    #else
            return OsTypeOther;
    #endif
        }
    
        enum HostArchitecture { HostArchitectureX86, HostArchitectureAMD64, HostArchitectureItanium, HostArchitectureArm, HostArchitectureUnknown };
        static HostArchitecture hostArchitecture();
    
        static constexpr bool isWindowsHost() { return hostOs() == OsTypeWindows; }
        static constexpr bool isLinuxHost() { return hostOs() == OsTypeLinux; }
        static constexpr bool isMacHost() { return hostOs() == OsTypeMac; }
        static constexpr bool isAnyUnixHost()
        {
    #ifdef Q_OS_UNIX
            return true;
    #else
            return false;
    #endif
        }
    
        static QString withExecutableSuffix(const QString &executable)
        {
            return OsSpecificAspects::withExecutableSuffix(hostOs(), executable);
        }
    
        static void setOverrideFileNameCaseSensitivity(Qt::CaseSensitivity sensitivity);
        static void unsetOverrideFileNameCaseSensitivity();
    	// 文件名大小写敏感检查 
        static Qt::CaseSensitivity fileNameCaseSensitivity()
        {
            return m_useOverrideFileNameCaseSensitivity
                    ? m_overrideFileNameCaseSensitivity
                    : OsSpecificAspects::fileNameCaseSensitivity(hostOs());
        }
    
        static QChar pathListSeparator()
        {
            return OsSpecificAspects::pathListSeparator(hostOs());
        }
    
        static Qt::KeyboardModifier controlModifier()
        {
            return OsSpecificAspects::controlModifier(hostOs());
        }
    
        static bool canCreateOpenGLContext(QString *errorMessage);
    
    private:
        static Qt::CaseSensitivity m_overrideFileNameCaseSensitivity;
        static bool m_useOverrideFileNameCaseSensitivity;
    };
    
    } // namespace Utils
    
    #include "hostosinfo.h"
    #include <QCoreApplication>
    
    #if !defined(QT_NO_OPENGL) && defined(QT_GUI_LIB)
    #include <QOpenGLContext>
    #endif
    
    #ifdef Q_OS_WIN
    #include <qt_windows.h>
    #endif
    
    using namespace Utils;
    
    //对静态函数进行初始化设置
    Qt::CaseSensitivity HostOsInfo::m_overrideFileNameCaseSensitivity = Qt::CaseSensitive;
    bool HostOsInfo::m_useOverrideFileNameCaseSensitivity = false;
    
    void HostOsInfo::setOverrideFileNameCaseSensitivity(Qt::CaseSensitivity sensitivity)
    {
        m_useOverrideFileNameCaseSensitivity = true;
        m_overrideFileNameCaseSensitivity = sensitivity;
    }
    void HostOsInfo::unsetOverrideFileNameCaseSensitivity()
    {
        m_useOverrideFileNameCaseSensitivity = false;
    }
    
    #ifdef Q_OS_WIN
    static WORD hostProcessorArchitecture()
    {
        SYSTEM_INFO info;
        GetNativeSystemInfo(&info); // 该函数在C:\Qt\Tools\mingw530_32\i686-w64-mingw32\include的sysinfoapi.h中
        return info.wProcessorArchitecture;
    }
    #endif
    
    HostOsInfo::HostArchitecture HostOsInfo::hostArchitecture()
    {
    #ifdef Q_OS_WIN
        static const WORD processorArchitecture = hostProcessorArchitecture();
        switch (processorArchitecture) {
        case PROCESSOR_ARCHITECTURE_AMD64: // 处于winnt.h中
            return HostOsInfo::HostArchitectureAMD64;
        case PROCESSOR_ARCHITECTURE_INTEL:
            return HostOsInfo::HostArchitectureX86;
        case PROCESSOR_ARCHITECTURE_IA64:
            return HostOsInfo::HostArchitectureItanium;
        case PROCESSOR_ARCHITECTURE_ARM:
            return HostOsInfo::HostArchitectureArm;
        default:
            return HostOsInfo::HostArchitectureUnknown;
        }
    #else
        return HostOsInfo::HostArchitectureUnknown;
    #endif
    }
    //检查能否使用OpenGL
    bool HostOsInfo::canCreateOpenGLContext(QString *errorMessage)
    {
    #if defined(QT_NO_OPENGL) || !defined(QT_GUI_LIB)
        Q_UNUSED(errorMessage)
        return false;
    #else
        static const bool canCreate = QOpenGLContext().create();
        if (!canCreate)
            *errorMessage = QCoreApplication::translate("Utils::HostOsInfo", "Cannot create OpenGL context.");
        return canCreate;
    #endif
    }
    
    展开全文
  • 内存键值存储的实现在Qt Creator软件源码的Utils中,文件名为namevaluedictionary和namevalueitem中。 NameValueItem 枚举类型Operation,有SetEnabled、Unset、Prepend、Append、SetDisabled。其主要有三种成员变量...

    内存键值存储的实现在Qt Creator软件源码的Utils中,文件名为namevaluedictionary和namevalueitem中。

    NameValueItem

    枚举类型Operation,有SetEnabled、Unset、Prepend、Append、SetDisabled。其主要有三种成员变量,即name、value和operation。其中name和value是QString类型,而operation是Operation类型的,默认为Unset。在构造函数中,operation变量回被设置成SetEnabled值。

    class QTCREATOR_UTILS_EXPORT NameValueItem
    {
    public:
        enum Operation : char { SetEnabled, Unset, Prepend, Append, SetDisabled };
        NameValueItem() = default;
        NameValueItem(const QString &key, const QString &value, Operation operation = SetEnabled) : name(key), value(value), operation(operation){}
        void apply(NameValueDictionary *dictionary) const { apply(dictionary, operation); }
        static void sort(NameValueItems *list) { Utils::sort(*list, &NameValueItem::name); }
        static NameValueItems fromStringList(const QStringList &list);
        static QStringList toStringList(const NameValueItems &list);
        static NameValueItems itemsFromVariantList(const QVariantList &list);
        static QVariantList toVariantList(const NameValueItems &list);
        static NameValueItem itemFromVariantList(const QVariantList &list);
        static QVariantList toVariantList(const NameValueItem &item);
        friend bool operator==(const NameValueItem &first, const NameValueItem &second)
        {
            return first.operation == second.operation && first.name == second.name
                   && first.value == second.value;
        }
        friend bool operator!=(const NameValueItem &first, const NameValueItem &second)
        {
            return !(first == second);
        }
    public:
        QString name;
        QString value;
        Operation operation = Unset;
    private:
        void apply(NameValueDictionary *dictionary, Operation op) const;
    };
    QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug debug, const NameValueItem &i)
    {
        QDebugStateSaver saver(debug);
        debug.noquote();
        debug.nospace();
        debug << "KeyValueItem(";
        switch (i.operation) {
        case NameValueItem::SetEnabled:
            debug << "set \"" << i.name << "\" to \"" << i.value << '"';
            break;
        case NameValueItem::SetDisabled:
            debug << "set \"" << i.name << "\" to \"" << i.value << '"' << "[disabled]";
            break;
        case NameValueItem::Unset:
            debug << "unset \"" << i.name << '"';
            break;
        case NameValueItem::Prepend:
            debug << "prepend to \"" << i.name << "\":\"" << i.value << '"';
            break;
        case NameValueItem::Append:
            debug << "append to \"" << i.name << "\":\"" << i.value << '"';
            break;
        }
        debug << ')';
        return debug;
    }
    using NameValueItems = QVector<NameValueItem>;
    

    fromStringList函数从QStringList中提取数据创建,当string中没有等于号时,创建name为string,value为空QString,Operation为Unset的NameValueItem。当string中有#和=时,提取#和=之间字符串作为name,=之后的设置为value,Operation为SetDisabled。只有等于号,则等于号前面的作为name,后面的作为value,Operation设置为SetEnabled。

    NameValueItems NameValueItem::fromStringList(const QStringList &list)
    {
        NameValueItems result;
        for (const QString &string : list) {
            int pos = string.indexOf('=', 1);
            if (pos == -1) {
                result.append(NameValueItem(string, QString(), NameValueItem::Unset));
                continue;
            }
            const int hashPos = string.indexOf('#');
            if (hashPos != -1 && hashPos < pos) {
                result.append({string.mid(hashPos + 1, pos - hashPos - 1), string.mid(pos + 1),
                               NameValueItem::SetDisabled});
            } else {
                result.append({string.left(pos), string.mid(pos + 1)});
            }
        }
        return result;
    }
    QStringList NameValueItem::toStringList(const NameValueItems &list)
    {
        return Utils::transform<QStringList>(list, [](const NameValueItem &item) {
            if (item.operation == NameValueItem::Unset)
                return QString(item.name);
            return QString((item.operation == NameValueItem::SetDisabled ? "#" : "")
                           + item.name + '=' + item.value);
        });
    }
    

    itemFromVariantList函数从QVariantList中提取键值存入NameValueItem返回。

    NameValueItem NameValueItem::itemFromVariantList(const QVariantList &list)
    {
        QTC_ASSERT(list.size() == 3, return NameValueItem("", ""));
        QString key = list.value(0).toString();
        Operation operation = Operation(list.value(1).toInt());
        QString value = list.value(2).toString();
        return NameValueItem(key, value, operation);
    }
    QVariantList NameValueItem::toVariantList(const NameValueItem &item)
    {
        return QVariantList() << item.name << item.operation << item.value;
    }
    

    apply是将值添加到字典中的私有函数,外界调用还有一个重载的apply是对这个函数的封装。

    enum : char {
    #ifdef Q_OS_WIN
        pathSepC = ';'
    #else
        pathSepC = ':'
    #endif
    };
    // 根据op对字典进行不同的操作
    void NameValueItem::apply(NameValueDictionary *dictionary, Operation op) const
    {
        switch (op) {
        case SetEnabled:
            dictionary->set(name, expand(dictionary, value));
            break;
        case SetDisabled:
            dictionary->set(name, expand(dictionary, value), false);
            break;
        case Unset:
            dictionary->unset(name);
            break;
        case Prepend: { // 前置
            const NameValueDictionary::const_iterator it = dictionary->constFind(name); // 从字典中找到该键值对
            if (it != dictionary->constEnd()) {  // 找到
                QString v = dictionary->value(it);  // 取出值
                const QChar pathSep{QLatin1Char(pathSepC)};
                int sepCount = 0;
                if (v.startsWith(pathSep)) // 去除多余pathSepC,没有就要添加
                    ++sepCount;
                if (value.endsWith(pathSep))
                    ++sepCount;
                if (sepCount == 2)
                    v.remove(0, 1);
                else if (sepCount == 0)
                    v.prepend(pathSep);
                v.prepend(expand(dictionary, value));
                dictionary->set(name, v);
            } else {
                apply(dictionary, SetEnabled); // 没有找到,就直接设置
            }
        } break;
        case Append: { // 附加
            const NameValueDictionary::const_iterator it = dictionary->constFind(name);
            if (it != dictionary->constEnd()) {
                QString v = dictionary->value(it);
                const QChar pathSep{QLatin1Char(pathSepC)};
                int sepCount = 0;
                if (v.endsWith(pathSep))
                    ++sepCount;
                if (value.startsWith(pathSep))
                    ++sepCount;
                if (sepCount == 2)
                    v.chop(1);
                else if (sepCount == 0)
                    v.append(pathSep);
                v.append(expand(dictionary, value));
                dictionary->set(name, v);
            } else {
                apply(dictionary, SetEnabled);
            }
        } break;
        }
    }
    

    expand函数尝试将$(key)${key}拓展为字典中key所代表的value值。如果不成功就将直接作为值设置。

    static QString expand(const NameValueDictionary *dictionary, QString value)
    {
        int replaceCount = 0;
        for (int i = 0; i < value.size(); ++i) {
            if (value.at(i) == '$') {
                if ((i + 1) < value.size()) {
                    const QChar &c = value.at(i + 1);
                    int end = -1;
                    if (c == '(')
                        end = value.indexOf(')', i);
                    else if (c == '{')
                        end = value.indexOf('}', i);
                    if (end != -1) {
                        const QString &key = value.mid(i + 2, end - i - 2);
                        NameValueDictionary::const_iterator it = dictionary->constFind(key);
                        if (it != dictionary->constEnd())
                            value.replace(i, end - i + 1, it.value().first);
                        ++replaceCount;
                        QTC_ASSERT(replaceCount < 100, break);
                    }
                }
            }
        }
        return value;
    }
    

    NameValueDictionary

    对字典的Key进行定制,包含对大小写敏感的控制。

    class QTCREATOR_UTILS_EXPORT DictKey
    {
    public:
        DictKey(const QString &name, Qt::CaseSensitivity cs) : name(name), caseSensitivity(cs) {}
        QString name;
        Qt::CaseSensitivity caseSensitivity;
    };
    inline bool operator<(const DictKey &k1, const DictKey &k2)
    {
        return k1.name.compare(k2.name, k1.caseSensitivity) < 0;
    }
    inline bool operator>(const DictKey &k1, const DictKey &k2) { return k2 < k1; }
    
    using NameValuePair = std::pair<QString, QString>;
    using NameValuePairs = QVector<NameValuePair>;
    using NameValueMap = QMap<DictKey, QPair<QString, bool>>;
    class QTCREATOR_UTILS_EXPORT NameValueDictionary
    {
    public:
        using const_iterator = NameValueMap::const_iterator;
        explicit NameValueDictionary(OsType osType = HostOsInfo::hostOs()) : m_osType(osType) {}
        explicit NameValueDictionary(const QStringList &env, OsType osType = HostOsInfo::hostOs());
        explicit NameValueDictionary(const NameValuePairs &nameValues);
        QStringList toStringList() const;
        QString value(const QString &key) const;
        void set(const QString &key, const QString &value, bool enabled = true);
        void unset(const QString &key);
        void modify(const NameValueItems &items);
        /// Return the KeyValueDictionary changes necessary to modify this into the other environment.
        NameValueItems diff(const NameValueDictionary &other, bool checkAppendPrepend = false) const;
        bool hasKey(const QString &key) const;
        OsType osType() const;
        Qt::CaseSensitivity nameCaseSensitivity() const;
        QString userName() const;
        void clear();
        int size() const;
        QString key(const_iterator it) const { return it.key().name; }
        QString value(const_iterator it) const { return it.value().first; }
        bool isEnabled(const_iterator it) const { return it.value().second; }
        const_iterator constBegin() const { return m_values.constBegin(); }
        const_iterator constEnd() const { return m_values.constEnd(); }
        const_iterator constFind(const QString &name) const;
        friend bool operator!=(const NameValueDictionary &first, const NameValueDictionary &second)
        {
            return !(first == second);
        }
        friend bool operator==(const NameValueDictionary &first, const NameValueDictionary &second)
        {
            return first.m_osType == second.m_osType && first.m_values == second.m_values;
        }
    protected:
        NameValueMap::iterator findKey(const QString &key);
        const_iterator findKey(const QString &key) const;
        NameValueMap m_values;
        OsType m_osType;
    };
    

    用于存储数据的数据结构是NameValueMap,它被定义为QMap<DictKey, QPair<QString, bool>>,也就是DictKey到QPair<QString, bool>的映射。这里的bool,其实就是对应上节的SetEnabled和SetDisabled。也就是数据中只存储Enabled和Disabled状态。
    针对字典键的查找函数:

    bool NameValueDictionary::hasKey(const QString &key) const
    {
        return findKey(key) != constEnd();
    }
    NameValueMap::iterator NameValueDictionary::findKey(const QString &key)
    {
        for (auto it = m_values.begin(); it != m_values.end(); ++it) {
            if (key.compare(it.key().name, nameCaseSensitivity()) == 0)
                return it;
        }
        return m_values.end();
    }
    NameValueMap::const_iterator NameValueDictionary::findKey(const QString &key) const
    {
        for (auto it = m_values.constBegin(); it != m_values.constEnd(); ++it) {
            if (key.compare(it.key().name, nameCaseSensitivity()) == 0)
                return it;
        }
        return m_values.constEnd();
    }
    

    设置和删除字典的记录

    void NameValueDictionary::set(const QString &key, const QString &value, bool enabled)
    {
        QTC_ASSERT(!key.contains('='), return );
        const auto it = findKey(key);
        const auto valuePair = qMakePair(value, enabled);
        if (it == m_values.end())  // 字典中没有,直接插入
            m_values.insert(DictKey(key, nameCaseSensitivity()), valuePair);
        else // 字典中有,直接改变值
            it.value() = valuePair;
    }
    // 这里unset就是直接删除记录
    void NameValueDictionary::unset(const QString &key)
    {
        QTC_ASSERT(!key.contains('='), return );
        const auto it = findKey(key);
        if (it != m_values.end())
            m_values.erase(it);
    }
    

    查找相应键的值,如果查不到,或者为Disabled状态直接返回空字符串。

    QString NameValueDictionary::value(const QString &key) const
    {
        const auto it = findKey(key);
        return it != m_values.end() && it.value().second ? it.value().first : QString();
    }
    

    NameValueDictionary的这个构造函数,将从QStringList的env引用提取键值对进行存储。

    NameValueDictionary::NameValueDictionary(const QStringList &env, OsType osType) : m_osType(osType) {
        for (const QString &s : env) {
            int i = s.indexOf('=', 1);
            if (i >= 0) {
                const QString key = s.left(i);
                if (!key.contains('=')) {
                    const QString value = s.mid(i + 1);
                    set(key, value);
                }
            }
        }
    }
    

    从QVector<td::pair<QString, QString>>提取参数,存入字典

    NameValueDictionary::NameValueDictionary(const NameValuePairs &nameValues)
    {
        for (const auto &nameValue : nameValues)
            set(nameValue.first, nameValue.second);
    }
    

    将NameValueItems提取创建新的字典替换现在的字典

    void NameValueDictionary::modify(const NameValueItems &items)
    {
        NameValueDictionary resultKeyValueDictionary = *this;
        for (const NameValueItem &item : items)
            item.apply(&resultKeyValueDictionary);
        *this = resultKeyValueDictionary;
    }
    

    序列化字典输出

    QStringList NameValueDictionary::toStringList() const
    {
        QStringList result;
        for (auto it = m_values.constBegin(); it != m_values.constEnd(); ++it) {
            if (it.value().second)
                result.append(it.key().name + '=' + it.value().first);
        }
        return result;
    }
    

    从内存键值存储中查询userName的值

    QString NameValueDictionary::userName() const
    {
        return value(QString::fromLatin1(m_osType == OsTypeWindows ? "USERNAME" : "USER"));
    }
    

    diff函数

    NameValueItems NameValueDictionary::diff(const NameValueDictionary &other, bool checkAppendPrepend) const
    {
        NameValueMap::const_iterator thisIt = constBegin();
        NameValueMap::const_iterator otherIt = other.constBegin();
    
        NameValueItems result;
        while (thisIt != constEnd() || otherIt != other.constEnd()) {
            if (thisIt == constEnd()) {
                result.append({other.key(otherIt), other.value(otherIt),
                    otherIt.value().second ? NameValueItem::SetEnabled : NameValueItem::SetDisabled});
                ++otherIt;
            } else if (otherIt == other.constEnd()) {
                result.append(NameValueItem(key(thisIt), QString(), NameValueItem::Unset));
                ++thisIt;
            } else if (thisIt.key() < otherIt.key()) {
                result.append(NameValueItem(key(thisIt), QString(), NameValueItem::Unset));
                ++thisIt;
            } else if (thisIt.key() > otherIt.key()) {
                result.append({other.key(otherIt), otherIt.value().first,
                    otherIt.value().second ? NameValueItem::SetEnabled : NameValueItem::SetDisabled});
                ++otherIt;
            } else {
                const QString &oldValue = thisIt.value().first;
                const QString &newValue = otherIt.value().first;
                const bool oldEnabled = thisIt.value().second;
                const bool newEnabled = otherIt.value().second;
                if (oldValue != newValue) {
                    if (checkAppendPrepend && newValue.startsWith(oldValue)
                            && oldEnabled == newEnabled) {
                        QString appended = newValue.right(newValue.size() - oldValue.size());
                        if (appended.startsWith(OsSpecificAspects::pathListSeparator(osType())))
                            appended.remove(0, 1);
                        result.append(NameValueItem(other.key(otherIt), appended, NameValueItem::Append));
                    } else if (checkAppendPrepend && newValue.endsWith(oldValue)
                               && oldEnabled == newEnabled) {
                        QString prepended = newValue.left(newValue.size() - oldValue.size());
                        if (prepended.endsWith(OsSpecificAspects::pathListSeparator(osType())))
                            prepended.chop(1);
                        result.append(NameValueItem(other.key(otherIt), prepended, NameValueItem::Prepend));
                    } else {
                        result.append({other.key(otherIt), newValue, newEnabled
                                ? NameValueItem::SetEnabled : NameValueItem::SetDisabled});
                    }
                }
                ++otherIt;
                ++thisIt;
            }
        }
        return result;
    }
    
    
    展开全文
  • 该篇文章内容主要集中Qt Creator软件欢迎界面部分代码的分析。从分析插件中的welcome模块开始,项目文件在路径\qt-creator-master\qt-creator-master\src\plugins\welcome下。 分析welcomeplugin.cpp文件 SideBar类...
  • 该篇文章内容主要集中Qt Creator软件界面部分代码的分析。从分析插件中的styledbar模块开始,项目文件在路径\qt-creator-master\qt-creator-master\src\libs\utils\utils-lib下。 StyleBar类 StyleBar类是Qt Creator...
  • AppMainWindow继承自QMainWindow类(#include <...class QTCREATOR_UTILS_EXPORT AppMainWindow : public QMainWindow { Q_OBJECT public: AppMainWindow(); public slots: void raiseWind...
  • 该篇文章内容主要集中Qt Creator软件界面部分代码的分析。从分析插件中的coreplugin中的fancyactionbar模块开始,项目文件在路径\qt-creator-master\qt-creator-master\src\plugins\coreplugin\下。 FancyActionBar...
  • 该篇文章内容主要集中Qt Creator软件界面部分代码的分析。从分析插件中的libs\utils中的theme模块开始,项目文件在路径\qt-creator-master\qt-creator-master\src\libs\utils\theme\下。 Theme类是创建主题和设置...
  • 该篇文章内容主要集中Qt Creator软件界面部分代码的分析。从分析插件中的plugins\coreplugin中的ThemeChooser模块开始,项目文件在路径\qt-creator-master\qt-creator-master\src\plugins\coreplugin\下。 涉及的三...
  • // Helper class holding all custom color values class QTCREATOR_UTILS_EXPORT StyleHelper { public: static const unsigned int DEFAULT_BASE_COLOR = 0x666666; static const int progressFadeAnimati...
  • 该篇文章内容主要集中Qt Creator软件欢迎界面部分代码的分析。从分析插件中的welcome模块开始,项目文件在路径\qt-creator-master\qt-creator-master\src\plugins\welcome下。 分析introductionwidget.cpp/.h文件 ...
  • 必须使用I_ID设置为“ org.qt-project.Qt.QtCreatorPlugin”的Q_PLUGIN_METADATA宏将IPlugin实现导出并告知Qt的插件系统。 读取插件的XML文件并找到依赖项之后,插件加载分为三个阶段: 所有插件库均以依赖树的...
  • QHash ,T>是Qt的通用容器类之一。 它存储(键,值)对,并提供与键关联的值的快速查找。QHash提供与QMap非常相似的功能。 不同之处在于:QHash提供比QMap更快的查找。 (有关详细信息,请参见算法复杂度。)遍历...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 224
精华内容 89
关键字:

qtcreator源码分析