• QT源码剖析之QSS样式表


    1. "QApplication::setStyleSheet()"设置样式表:

      1. 创建新的样式表。

      2. 设置新的样式。

    void QApplication::setStyleSheet(const QString& styleSheet)
    {
        QApplicationPrivate::styleSheet = styleSheet;
        QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplicationPrivate::app_style);
        if (styleSheet.isEmpty()) { // application style sheet removed
            if (!proxy)
                return; // there was no stylesheet before
            setStyle(proxy->base);
        } else if (proxy) { // style sheet update, just repolish
            proxy->repolish(qApp);
        } else { // stylesheet set the first time
            QStyleSheetStyle *newProxy = new QStyleSheetStyle(QApplicationPrivate::app_style);
            QApplicationPrivate::app_style->setParent(newProxy);
            setStyle(newProxy);
        }
    }

    2. "QApplication::setStyle"——设置样式:

    void QApplication::setStyle(QStyle *style)
    {
        if (!style || style == QApplicationPrivate::app_style)
            return;
    
        QWidgetList all = allWidgets();
    
        // clean up the old style
        if (QApplicationPrivate::app_style) {
            if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
                for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) {
                    QWidget *w = *it;
                    if (!(w->windowType() == Qt::Desktop) &&        // except desktop
                         w->testAttribute(Qt::WA_WState_Polished)) { // has been polished
                        QApplicationPrivate::app_style->unpolish(w);
                    }
                }
            }
            QApplicationPrivate::app_style->unpolish(qApp);
        }
    
        QStyle *old = QApplicationPrivate::app_style; // save
    
        QApplicationPrivate::overrides_native_style =
            nativeStyleClassName() == QByteArray(style->metaObject()->className());
    
    #ifndef QT_NO_STYLE_STYLESHEET
        if (!QApplicationPrivate::styleSheet.isEmpty() && !qobject_cast<QStyleSheetStyle *>(style)) {
            // we have a stylesheet already and a new style is being set
            QStyleSheetStyle *newProxy = new QStyleSheetStyle(style);
            style->setParent(newProxy);
            QApplicationPrivate::app_style = newProxy;
        } else
    #endif // QT_NO_STYLE_STYLESHEET
            QApplicationPrivate::app_style = style;
        QApplicationPrivate::app_style->setParent(qApp); // take ownership
    
        // take care of possible palette requirements of certain gui
        // styles. Do it before polishing the application since the style
        // might call QApplication::setPalette() itself
        if (QApplicationPrivate::set_pal) {
            QApplication::setPalette(*QApplicationPrivate::set_pal);
        } else if (QApplicationPrivate::sys_pal) {
            clearSystemPalette();
            initSystemPalette();
            QApplicationPrivate::initializeWidgetPaletteHash();
            QApplicationPrivate::initializeWidgetFontHash();
            QApplicationPrivate::setPalette_helper(*QApplicationPrivate::sys_pal, /*className=*/0, /*clearWidgetPaletteHash=*/false);
        } else if (!QApplicationPrivate::sys_pal) {
            // Initialize the sys_pal if it hasn't happened yet...
            QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette());
        }
    
        // initialize the application with the new style
        QApplicationPrivate::app_style->polish(qApp);
    
        // re-polish existing widgets if necessary
        if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
            for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) {
                QWidget *w = *it;
                if (w->windowType() != Qt::Desktop && w->testAttribute(Qt::WA_WState_Polished)) {
                    if (w->style() == QApplicationPrivate::app_style)
                        QApplicationPrivate::app_style->polish(w);                // repolish
    #ifndef QT_NO_STYLE_STYLESHEET
                    else
                        w->setStyleSheet(w->styleSheet()); // touch
    #endif
                }
            }
    
            for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) {
                QWidget *w = *it;
                if (w->windowType() != Qt::Desktop && !w->testAttribute(Qt::WA_SetStyle)) {
                        QEvent e(QEvent::StyleChange);
                        QApplication::sendEvent(w, &e);
                        w->update();
                }
            }
        }
    
    #ifndef QT_NO_STYLE_STYLESHEET
        if (QStyleSheetStyle *oldProxy = qobject_cast<QStyleSheetStyle *>(old)) {
            oldProxy->deref();
        } else
    #endif
        if (old && old->parent() == qApp) {
            delete old;
        }
    
        if (QApplicationPrivate::focus_widget) {
            QFocusEvent in(QEvent::FocusIn, Qt::OtherFocusReason);
            QApplication::sendEvent(QApplicationPrivate::focus_widget->style(), &in);
            QApplicationPrivate::focus_widget->update();
        }
    }

      2-1. 获取所有的QWidget列表(在QWidget的构造函数中调用QWidgetPrivate::init函数,将当前QWidget加入到列表)。

      2-2. 移除所有QWidget上旧的样式。

      2-3. 设置所有QWidget新的样式。

      2-4. 更新所有的QWidget。

    4. "QStyleSheetStyle::styleRules"——经过一系列调用到这个函数中,获取样式规则:

    QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QObject *obj) const
    {
        QHash<const QObject *, QVector<StyleRule> >::const_iterator cacheIt = styleSheetCaches->styleRulesCache.constFind(obj);
        if (cacheIt != styleSheetCaches->styleRulesCache.constEnd())
            return cacheIt.value();
    
        if (!initObject(obj)) {
            return QVector<StyleRule>();
        }
    
        QStyleSheetStyleSelector styleSelector;
    
        StyleSheet defaultSs;
        QHash<const void *, StyleSheet>::const_iterator defaultCacheIt = styleSheetCaches->styleSheetCache.constFind(baseStyle());
        if (defaultCacheIt == styleSheetCaches->styleSheetCache.constEnd()) {
            defaultSs = getDefaultStyleSheet();
            QStyle *bs = baseStyle();
            styleSheetCaches->styleSheetCache.insert(bs, defaultSs);
            QObject::connect(bs, SIGNAL(destroyed(QObject*)), styleSheetCaches, SLOT(styleDestroyed(QObject*)), Qt::UniqueConnection);
        } else {
            defaultSs = defaultCacheIt.value();
        }
        styleSelector.styleSheets += defaultSs;
    
        if (!qApp->styleSheet().isEmpty()) {
            StyleSheet appSs;
            QHash<const void *, StyleSheet>::const_iterator appCacheIt = styleSheetCaches->styleSheetCache.constFind(qApp);
            if (appCacheIt == styleSheetCaches->styleSheetCache.constEnd()) {
                QString ss = qApp->styleSheet();
                if (ss.startsWith(QLatin1String("file:///")))
                    ss.remove(0, 8);
                parser.init(ss, qApp->styleSheet() != ss);
                if (!parser.parse(&appSs))
                    qWarning("Could not parse application stylesheet");
                appSs.origin = StyleSheetOrigin_Inline;
                appSs.depth = 1;
                styleSheetCaches->styleSheetCache.insert(qApp, appSs);
            } else {
                appSs = appCacheIt.value();
            }
            styleSelector.styleSheets += appSs;
        }
    
        QVector<QCss::StyleSheet> objectSs;
        for (const QObject *o = obj; o; o = parentObject(o)) {
            QString styleSheet = o->property("styleSheet").toString();
            if (styleSheet.isEmpty())
                continue;
            StyleSheet ss;
            QHash<const void *, StyleSheet>::const_iterator objCacheIt = styleSheetCaches->styleSheetCache.constFind(o);
            if (objCacheIt == styleSheetCaches->styleSheetCache.constEnd()) {
                parser.init(styleSheet);
                if (!parser.parse(&ss)) {
                    parser.init(QLatin1String("* {") + styleSheet + QLatin1Char('}'));
                    if (!parser.parse(&ss))
                       qWarning("Could not parse stylesheet of object %p", o);
                }
                ss.origin = StyleSheetOrigin_Inline;
                styleSheetCaches->styleSheetCache.insert(o, ss);
            } else {
                ss = objCacheIt.value();
            }
            objectSs.append(ss);
        }
    
        for (int i = 0; i < objectSs.count(); i++)
            objectSs[i].depth = objectSs.count() - i + 2;
    
        styleSelector.styleSheets += objectSs;
    
        StyleSelector::NodePtr n;
        n.ptr = const_cast<QObject *>(obj);
        QVector<QCss::StyleRule> rules = styleSelector.styleRulesForNode(n);
        styleSheetCaches->styleRulesCache.insert(obj, rules);
        return rules;
    }

      4-1. 初始化如果缓存中没有样式,先进行初始化。

      4-2. 获取基本样式到@defaultSs中,并添加到@styleSelector.styleSheets

      4-3. 在缓存中获取全局@qApp样式到@appSs中,并添加到@styleSelector.styleSheets。

        4-3-1. 如果在缓存中没有找到全局@qApp样式,则获取@qApp样式表字符串进行解析生成StyleSheet

      4-4. 不断遍历基类,从缓存中获取基类的样式到@objectSs中,并添加到@styleSelector.styleSheets。

        4-4-1. 如果缓存没有找到样式,则利用字符串重新解析生成StyleSheet

      4-5. 根据样式选着器(QStyleSheetStyleSelector)获取样式规添加到@rules。

      4-6. 最后将对象(QObject)与样式规则(StyleRule)插入到缓存@styleSheetCaches->styleRulesCache中。

    5. 将字符串解析生成样式表StyleSheet(主要在qcssparser.cpp文件中):

      在"QStyleSheetStyle::styleRules"主要通过通过两个函数"Parser::init"和"Parser::parse"。

      5-1. 初始化解析器:

    void Parser::init(const QString &css, bool isFile)
    {
        QString styleSheet = css;
        if (isFile) {
            QFile file(css);
            if (file.open(QFile::ReadOnly)) {
                sourcePath = QFileInfo(styleSheet).absolutePath() + QLatin1Char('/');
                QTextStream stream(&file);
                styleSheet = stream.readAll();
            } else {
                qWarning() << "QCss::Parser - Failed to load file " << css;
                styleSheet.clear();
            }
        } else {
            sourcePath.clear();
        }
    
        hasEscapeSequences = false;
        symbols.resize(0);
        symbols.reserve(8);
        Scanner::scan(Scanner::preprocess(styleSheet, &hasEscapeSequences), &symbols);
        index = 0;
        errorIndex = -1;
    }

        5-1-1. 将字符串进行预处理(这里主要是处理转义字符)。

        5-1-2. 逐个扫描形成一个一个符号(与编译原理中的扫描程序一致,形成符号后,方便后面进一步处理)。

      5-2. 解析样式表:

    bool Parser::parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity)
    {
        if (testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("charset"))) {
            if (!next(STRING)) return false;
            if (!next(SEMICOLON)) return false;
        }
    
        while (test(S) || test(CDO) || test(CDC)) {}
    
        while (testImport()) {
            ImportRule rule;
            if (!parseImport(&rule)) return false;
            styleSheet->importRules.append(rule);
            while (test(S) || test(CDO) || test(CDC)) {}
        }
    
        do {
            if (testMedia()) {
                MediaRule rule;
                if (!parseMedia(&rule)) return false;
                styleSheet->mediaRules.append(rule);
            } else if (testPage()) {
                PageRule rule;
                if (!parsePage(&rule)) return false;
                styleSheet->pageRules.append(rule);
            } else if (testRuleset()) {
                StyleRule rule;
                if (!parseRuleset(&rule)) return false;
                styleSheet->styleRules.append(rule);
            } else if (test(ATKEYWORD_SYM)) {
                if (!until(RBRACE)) return false;
            } else if (hasNext()) {
                return false;
            }
            while (test(S) || test(CDO) || test(CDC)) {}
        } while (hasNext());
        styleSheet->buildIndexes(nameCaseSensitivity);
        return true;
    }

        5-2-1. 遍历所有符号,根据符号的类型进行相应的处理(这里我们只关注样式规则"parseRuleset(&rule)")。

        5-2-2. 解析样式规则:

    bool Parser::parseRuleset(StyleRule *styleRule)
    {
        Selector sel;
        if (!parseSelector(&sel)) return false;
        styleRule->selectors.append(sel);
    
        while (test(COMMA)) {
            skipSpace();
            Selector sel;
            if (!parseNextSelector(&sel)) return false;
            styleRule->selectors.append(sel);
        }
    
        skipSpace();
        if (!next(LBRACE)) return false;
        const int declarationStart = index;
    
        do {
            skipSpace();
            Declaration decl;
            const int rewind = index;
            if (!parseNextDeclaration(&decl)) {
                index = rewind;
                const bool foundSemicolon = until(SEMICOLON);
                const int semicolonIndex = index;
    
                index = declarationStart;
                const bool foundRBrace = until(RBRACE);
    
                if (foundSemicolon && semicolonIndex < index) {
                    decl = Declaration();
                    index = semicolonIndex - 1;
                } else {
                    skipSpace();
                    return foundRBrace;
                }
            }
            if (!decl.isEmpty())
                styleRule->declarations.append(decl);
        } while (test(SEMICOLON));
    
        if (!next(RBRACE)) return false;
        skipSpace();
        return true;
    }

        5-2-2-1. 解析选择器(id选着器,class选着器,属性选着器等)。

        5-2-2-2. 解析声明,包括属性名、属性值等。

        5-2-2-3. 将解析的声明添加到样式规则中。

     6. (4-5的细化)根据样式选着器(QStyleSheetStyleSelector)得到样式规则"":

     1 QVector<StyleRule> StyleSelector::styleRulesForNode(NodePtr node)
     2 {
     3     QVector<StyleRule> rules;
     4     if (styleSheets.isEmpty())
     5         return rules;
     6 
     7     QMap<uint, StyleRule> weightedRules; // (spec, rule) that will be sorted below
     8 
     9     //prune using indexed stylesheet
    10     for (int sheetIdx = 0; sheetIdx < styleSheets.count(); ++sheetIdx) {
    11         const StyleSheet &styleSheet = styleSheets.at(sheetIdx);
    12         for (int i = 0; i < styleSheet.styleRules.count(); ++i) {
    13             matchRule(node, styleSheet.styleRules.at(i), styleSheet.origin, styleSheet.depth, &weightedRules);
    14         }
    15 
    16         if (!styleSheet.idIndex.isEmpty()) {
    17             QStringList ids = nodeIds(node);
    18             for (int i = 0; i < ids.count(); i++) {
    19                 const QString &key = ids.at(i);
    20                 QMultiHash<QString, StyleRule>::const_iterator it = styleSheet.idIndex.constFind(key);
    21                 while (it != styleSheet.idIndex.constEnd() && it.key() == key) {
    22                     matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules);
    23                     ++it;
    24                 }
    25             }
    26         }
    27         if (!styleSheet.nameIndex.isEmpty()) {
    28             QStringList names = nodeNames(node);
    29             for (int i = 0; i < names.count(); i++) {
    30                 QString name = names.at(i);
    31                 if (nameCaseSensitivity == Qt::CaseInsensitive)
    32                     name = name.toLower();
    33                 QMultiHash<QString, StyleRule>::const_iterator it = styleSheet.nameIndex.constFind(name);
    34                 while (it != styleSheet.nameIndex.constEnd() && it.key() == name) {
    35                     matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules);
    36                     ++it;
    37                 }
    38             }
    39         }
    40         if (!medium.isEmpty()) {
    41             for (int i = 0; i < styleSheet.mediaRules.count(); ++i) {
    42                 if (styleSheet.mediaRules.at(i).media.contains(medium, Qt::CaseInsensitive)) {
    43                     for (int j = 0; j < styleSheet.mediaRules.at(i).styleRules.count(); ++j) {
    44                         matchRule(node, styleSheet.mediaRules.at(i).styleRules.at(j), styleSheet.origin,
    45                                styleSheet.depth, &weightedRules);
    46                     }
    47                 }
    48             }
    49         }
    50     }
    51 
    52     rules.reserve(weightedRules.count());
    53     QMap<uint, StyleRule>::const_iterator it = weightedRules.constBegin();
    54     for ( ; it != weightedRules.constEnd() ; ++it)
    55         rules += *it;
    56 
    57     return rules;
    58 }

      6-1. 遍历已有的样式规则(styleSheet.styleRules),如果匹配规则,将规则添加到@weightedRules中。

      6-2. 遍历id样式(styleSheet.idIndex),获取当前对象的名称(objectName),对象名称相同则匹配规则,将匹配的规则添加到@weightedRules中。

      6-3. 遍历class样式(styleSheet.nameIndex),获取当前对象的类名称(className)和基类的类名称,类名称相同则匹配规则,将规则添加到@weightedRules中。

      6-4. 将@weightedRules中的样式规则添加到@rules,并返回@rules

    7. 最后需要渲染规则,将得到的样式规则转换为绘制时需要的对象(字体、颜色、背景画刷、背景图片等等):

    QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject *object)
    : features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), ou(0), geo(0), p(0), img(0), clipset(0)
    {
        QPalette palette = QApplication::palette(); // ###: ideally widget's palette
        ValueExtractor v(declarations, palette)zhua
        features = v.extractStyleFeatures();
    
        int w = -1, h = -1, minw = -1, minh = -1, maxw = -1, maxh = -1;
        if (v.extractGeometry(&w, &h, &minw, &minh, &maxw, &maxh))
            geo = new QStyleSheetGeometryData(w, h, minw, minh, maxw, maxh);
    
        int left = 0, top = 0, right = 0, bottom = 0;
        Origin origin = Origin_Unknown;
        Qt::Alignment position = 0;
        QCss::PositionMode mode = PositionMode_Unknown;
        Qt::Alignment textAlignment = 0;
        if (v.extractPosition(&left, &top, &right, &bottom, &origin, &position, &mode, &textAlignment))
            p = new QStyleSheetPositionData(left, top, right, bottom, origin, position, mode, textAlignment);
    
        int margins[4], paddings[4], spacing = -1;
        for (int i = 0; i < 4; i++)
            margins[i] = paddings[i] = 0;
        if (v.extractBox(margins, paddings, &spacing))
            b = new QStyleSheetBoxData(margins, paddings, spacing);
    
        int borders[4];
        QBrush colors[4];
        QCss::BorderStyle styles[4];
        QSize radii[4];
        for (int i = 0; i < 4; i++) {
            borders[i] = 0;
            styles[i] = BorderStyle_None;
        }
        if (v.extractBorder(borders, colors, styles, radii))
            bd = new QStyleSheetBorderData(borders, colors, styles, radii);
    
        int offsets[4];
        for (int i = 0; i < 4; i++) {
            borders[i] = offsets[i] = 0;
            styles[i] = BorderStyle_None;
        }
        if (v.extractOutline(borders, colors, styles, radii, offsets))
            ou = new QStyleSheetOutlineData(borders, colors, styles, radii, offsets);
    
        QBrush brush;
        QString uri;
        Repeat repeat = Repeat_XY;
        Qt::Alignment alignment = Qt::AlignTop | Qt::AlignLeft;
        Attachment attachment = Attachment_Scroll;
        origin = Origin_Padding;
        Origin clip = Origin_Border;
        if (v.extractBackground(&brush, &uri, &repeat, &alignment, &origin, &attachment, &clip))
            bg = new QStyleSheetBackgroundData(brush, QPixmap(uri), repeat, alignment, origin, attachment, clip);
    
        QBrush sfg, fg;
        QBrush sbg, abg;
        if (v.extractPalette(&fg, &sfg, &sbg, &abg))
            pal = new QStyleSheetPaletteData(fg, sfg, sbg, abg);
    
        QIcon icon;
        alignment = Qt::AlignCenter;
        QSize size;
        if (v.extractImage(&icon, &alignment, &size))
            img = new QStyleSheetImageData(icon, alignment, size);
    
        int adj = -255;
        hasFont = v.extractFont(&font, &adj);
    
    #ifndef QT_NO_TOOLTIP
        if (object && qstrcmp(object->metaObject()->className(), "QTipLabel") == 0)
            palette = QToolTip::palette();
    #endif
    
        for (int i = 0; i < declarations.count(); i++) {
            const Declaration& decl = declarations.at(i);
            if (decl.d->propertyId == BorderImage) {
                QString uri;
                QCss::TileMode horizStretch, vertStretch;
                int cuts[4];
    
                decl.borderImageValue(&uri, cuts, &horizStretch, &vertStretch);
                if (uri.isEmpty() || uri == QLatin1String("none")) {
                    if (bd && bd->bi)
                        bd->bi->pixmap = QPixmap();
                } else {
                    if (!bd)
                        bd = new QStyleSheetBorderData;
                    if (!bd->bi)
                        bd->bi = new QStyleSheetBorderImageData;
    
                    QStyleSheetBorderImageData *bi = bd->bi;
                    bi->pixmap = QPixmap(uri);
                    for (int i = 0; i < 4; i++)
                        bi->cuts[i] = cuts[i];
                    bi->horizStretch = horizStretch;
                    bi->vertStretch = vertStretch;
                }
            } else if (decl.d->propertyId == QtBackgroundRole) {
                if (bg && bg->brush.style() != Qt::NoBrush)
                    continue;
                int role = decl.d->values.at(0).variant.toInt();
                if (role >= Value_FirstColorRole && role <= Value_LastColorRole)
                    defaultBackground = palette.color((QPalette::ColorRole)(role-Value_FirstColorRole));
            } else if (decl.d->property.startsWith(QLatin1String("qproperty-"), Qt::CaseInsensitive)) {
                // intentionally left blank...
            } else if (decl.d->propertyId == UnknownProperty) {
                bool knownStyleHint = false;
                for (int i = 0; i < numKnownStyleHints; i++) {
                    QLatin1String styleHint(knownStyleHints[i]);
                    if (decl.d->property.compare(styleHint) == 0) {
                       QString hintName = QString(styleHint);
                       QVariant hintValue;
                       if (hintName.endsWith(QLatin1String("alignment"))) {
                           hintValue = (int) decl.alignmentValue();
                       } else if (hintName.endsWith(QLatin1String("color"))) {
                           hintValue = (int) decl.colorValue().rgba();
                       } else if (hintName.endsWith(QLatin1String("size"))) {
                           hintValue = decl.sizeValue();
                       } else if (hintName.endsWith(QLatin1String("icon"))) {
                           hintValue = decl.iconValue();
                       } else if (hintName == QLatin1String("button-layout")
                                  && decl.d->values.count() != 0 && decl.d->values.at(0).type == Value::String) {
                           hintValue = subControlLayout(decl.d->values.at(0).variant.toString());
                       } else {
                           int integer;
                           decl.intValue(&integer);
                           hintValue = integer;
                       }
                       styleHints[decl.d->property] = hintValue;
                       knownStyleHint = true;
                       break;
                    }
                }
                if (!knownStyleHint)
                    qDebug("Unknown property %s", qPrintable(decl.d->property));
            }
        }
    
        if (const QWidget *widget = qobject_cast<const QWidget *>(object)) {
            QStyleSheetStyle *style = const_cast<QStyleSheetStyle *>(globalStyleSheetStyle);
            if (!style)
                style = qobject_cast<QStyleSheetStyle *>(widget->style());
            if (style)
                fixupBorder(style->nativeFrameWidth(widget));
        }
        if (hasBorder() && border()->hasBorderImage())
            defaultBackground = QBrush();
    }

      从样式规则中得到样式声明,然后根据样式声明去创建不同的绘制对象,为后面的绘制做准备。

      绘制对象包括:位置(Geomeory、Position、Box)、边框(Border、Outline)、背景(BackgroundColor、BackgroundImage等)、字体(FontFamily、FontSize、FontStyle、FontWeight等)等等。

    最后如果想查看QSS属性名称和值的列表,可以查看qtbasesrcgui extqcssparser.cpp文件:

    static const QCssKnownValue properties[NumProperties - 1] = {
        { "-qt-background-role", QtBackgroundRole },
        { "-qt-block-indent", QtBlockIndent },
        { "-qt-list-indent", QtListIndent },
        { "-qt-list-number-prefix", QtListNumberPrefix },
        { "-qt-list-number-suffix", QtListNumberSuffix },
        { "-qt-paragraph-type", QtParagraphType },
        { "-qt-style-features", QtStyleFeatures },
        { "-qt-table-type", QtTableType },
        { "-qt-user-state", QtUserState },
        { "alternate-background-color", QtAlternateBackground },
        { "background", Background },
        { "background-attachment", BackgroundAttachment },
        { "background-clip", BackgroundClip },
        { "background-color", BackgroundColor },
        { "background-image", BackgroundImage },
        { "background-origin", BackgroundOrigin },
        { "background-position", BackgroundPosition },
        { "background-repeat", BackgroundRepeat },
        { "border", Border },
        { "border-bottom", BorderBottom },
        { "border-bottom-color", BorderBottomColor },
        { "border-bottom-left-radius", BorderBottomLeftRadius },
        { "border-bottom-right-radius", BorderBottomRightRadius },
        { "border-bottom-style", BorderBottomStyle },
        { "border-bottom-width", BorderBottomWidth },
        { "border-color", BorderColor },
        { "border-image", BorderImage },
        { "border-left", BorderLeft },
        { "border-left-color", BorderLeftColor },
        { "border-left-style", BorderLeftStyle },
        { "border-left-width", BorderLeftWidth },
        { "border-radius", BorderRadius },
        { "border-right", BorderRight },
        { "border-right-color", BorderRightColor },
        { "border-right-style", BorderRightStyle },
        { "border-right-width", BorderRightWidth },
        { "border-style", BorderStyles },
        { "border-top", BorderTop },
        { "border-top-color", BorderTopColor },
        { "border-top-left-radius", BorderTopLeftRadius },
        { "border-top-right-radius", BorderTopRightRadius },
        { "border-top-style", BorderTopStyle },
        { "border-top-width", BorderTopWidth },
        { "border-width", BorderWidth },
        { "bottom", Bottom },
        { "color", Color },
        { "float", Float },
        { "font", Font },
        { "font-family", FontFamily },
        { "font-size", FontSize },
        { "font-style", FontStyle },
        { "font-variant", FontVariant },
        { "font-weight", FontWeight },
        { "height", Height },
        { "image", QtImage },
        { "image-position", QtImageAlignment },
        { "left", Left },
        { "line-height", LineHeight },
        { "list-style", ListStyle },
        { "list-style-type", ListStyleType },
        { "margin" , Margin },
        { "margin-bottom", MarginBottom },
        { "margin-left", MarginLeft },
        { "margin-right", MarginRight },
        { "margin-top", MarginTop },
        { "max-height", MaximumHeight },
        { "max-width", MaximumWidth },
        { "min-height", MinimumHeight },
        { "min-width", MinimumWidth },
        { "outline", Outline },
        { "outline-bottom-left-radius", OutlineBottomLeftRadius },
        { "outline-bottom-right-radius", OutlineBottomRightRadius },
        { "outline-color", OutlineColor },
        { "outline-offset", OutlineOffset },
        { "outline-radius", OutlineRadius },
        { "outline-style", OutlineStyle },
        { "outline-top-left-radius", OutlineTopLeftRadius },
        { "outline-top-right-radius", OutlineTopRightRadius },
        { "outline-width", OutlineWidth },
        { "padding", Padding },
        { "padding-bottom", PaddingBottom },
        { "padding-left", PaddingLeft },
        { "padding-right", PaddingRight },
        { "padding-top", PaddingTop },
        { "page-break-after", PageBreakAfter },
        { "page-break-before", PageBreakBefore },
        { "position", Position },
        { "right", Right },
        { "selection-background-color", QtSelectionBackground },
        { "selection-color", QtSelectionForeground },
        { "spacing", QtSpacing },
        { "subcontrol-origin", QtOrigin },
        { "subcontrol-position", QtPosition },
        { "text-align", TextAlignment },
        { "text-decoration", TextDecoration },
        { "text-indent", TextIndent },
        { "text-transform", TextTransform },
        { "text-underline-style", TextUnderlineStyle },
        { "top", Top },
        { "vertical-align", VerticalAlignment },
        { "white-space", Whitespace },
        { "width", Width }
    };
    
    static const QCssKnownValue values[NumKnownValues - 1] = {
        { "active", Value_Active },
        { "alternate-base", Value_AlternateBase },
        { "always", Value_Always },
        { "auto", Value_Auto },
        { "base", Value_Base },
        { "bold", Value_Bold },
        { "bottom", Value_Bottom },
        { "bright-text", Value_BrightText },
        { "button", Value_Button },
        { "button-text", Value_ButtonText },
        { "center", Value_Center },
        { "circle", Value_Circle },
        { "dark", Value_Dark },
        { "dashed", Value_Dashed },
        { "decimal", Value_Decimal },
        { "disabled", Value_Disabled },
        { "disc", Value_Disc },
        { "dot-dash", Value_DotDash },
        { "dot-dot-dash", Value_DotDotDash },
        { "dotted", Value_Dotted },
        { "double", Value_Double },
        { "groove", Value_Groove },
        { "highlight", Value_Highlight },
        { "highlighted-text", Value_HighlightedText },
        { "inset", Value_Inset },
        { "italic", Value_Italic },
        { "large", Value_Large },
        { "left", Value_Left },
        { "light", Value_Light },
        { "line-through", Value_LineThrough },
        { "link", Value_Link },
        { "link-visited", Value_LinkVisited },
        { "lower-alpha", Value_LowerAlpha },
        { "lower-roman", Value_LowerRoman },
        { "lowercase", Value_Lowercase },
        { "medium", Value_Medium },
        { "mid", Value_Mid },
        { "middle", Value_Middle },
        { "midlight", Value_Midlight },
        { "native", Value_Native },
        { "none", Value_None },
        { "normal", Value_Normal },
        { "nowrap", Value_NoWrap },
        { "oblique", Value_Oblique },
        { "off", Value_Off },
        { "on", Value_On },
        { "outset", Value_Outset },
        { "overline", Value_Overline },
        { "pre", Value_Pre },
        { "pre-wrap", Value_PreWrap },
        { "ridge", Value_Ridge },
        { "right", Value_Right },
        { "selected", Value_Selected },
        { "shadow", Value_Shadow },
        { "small" , Value_Small },
        { "small-caps", Value_SmallCaps },
        { "solid", Value_Solid },
        { "square", Value_Square },
        { "sub", Value_Sub },
        { "super", Value_Super },
        { "text", Value_Text },
        { "top", Value_Top },
        { "transparent", Value_Transparent },
        { "underline", Value_Underline },
        { "upper-alpha", Value_UpperAlpha },
        { "upper-roman", Value_UpperRoman },
        { "uppercase", Value_Uppercase },
        { "wave", Value_Wave },
        { "window", Value_Window },
        { "window-text", Value_WindowText },
        { "x-large", Value_XLarge },
        { "xx-large", Value_XXLarge }
    };
  • 相关阅读:
    JS 的execCommand 方法 做的一个简单富文本
    机器学习入门
    code practice websites
    机器学习 入门参考资料
    const型变量与函数重载
    数组是否应该初始化?
    翻译:编译器内部的秘密微软的编译器是如何解析Try/Catch/Throw的
    在C++中用C#风格设置类的属性值

    记可敬可佩的老车同志
  • 原文地址:https://www.cnblogs.com/dongc/p/5512849.html
Copyright © 2020-2023  润新知