📄 qstylesheetstyle.cpp
字号:
"lineedit-password-character", "menubar-altkey-navigation", "menubar-separator", "menu-scrollable", "messagebox-text-interaction-flags", "mouse-tracking", "opacity", "scrollbar-contextmenu", "scrollbar-leftclick-absolute-position", "scrollbar-middleclick-absolute-position", "scrollbar-roll-between-buttons", "scrollbar-scroll-when-pointer-leaves-control", "scrollview-frame-around-contents", "show-decoration-selected", "spinbox-click-autorepeat-rate", "spincontrol-disable-on-bounds", "tabbar-elide-mode", "tabbar-prefer-no-arrows", "toolbutton-popup-delay"};static const int numKnownStyleHints = sizeof(knownStyleHints)/sizeof(knownStyleHints[0]);QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QWidget *widget): features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), geo(0), p(0), img(0), clipset(0){ Q_ASSERT(widget); QPalette palette = qApp->palette(); // ###: ideally widget's palette ValueExtractor v(declarations, palette); 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); 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 (QString::fromLatin1(widget->metaObject()->className()) == QLatin1String("QTipLabel")) palette = QToolTip::palette();#endif for (int i = 0; i < declarations.count(); i++) { const Declaration& decl = declarations.at(i); if (decl.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.propertyId == QtBackgroundRole) { if (bg && bg->brush.style() != Qt::NoBrush) continue; int role = decl.values.first().variant.toInt(); if (role >= Value_FirstColorRole && role <= Value_LastColorRole) defaultBackground = palette.color((QPalette::ColorRole)(role-Value_FirstColorRole)); } else if (decl.property.startsWith(QLatin1String("qproperty-"), Qt::CaseInsensitive)) { } else if (decl.propertyId == UnknownProperty) { bool knownStyleHint = false; for (int i = 0; i < numKnownStyleHints; i++) { QLatin1String styleHint(knownStyleHints[i]); if (decl.property.compare(styleHint) == 0) { int hint; if (QString(styleHint).endsWith(QLatin1String("alignment"))) { hint = (int) decl.alignmentValue(); } else { decl.intValue(&hint); } styleHints[decl.property] = hint; knownStyleHint = true; break; } } if (!knownStyleHint) qWarning("Unknown property %s", qPrintable(decl.property)); } } QStyleSheetStyle *style = qobject_cast<QStyleSheetStyle *>(widget->style()); Q_ASSERT(style); fixupBorder(style->nativeFrameWidth(widget)); if (hasBorder() && border()->hasBorderImage()) defaultBackground = QBrush();}QRect QRenderRule::borderRect(const QRect& r) const{ if (!hasBox()) return r; const int* m = box()->margins; return r.adjusted(m[LeftEdge], m[TopEdge], -m[RightEdge], -m[BottomEdge]);}QRect QRenderRule::paddingRect(const QRect& r) const{ QRect br = borderRect(r); if (!hasBorder()) return br; const int *b = border()->borders; return br.adjusted(b[LeftEdge], b[TopEdge], -b[RightEdge], -b[BottomEdge]);}QRect QRenderRule::contentsRect(const QRect& r) const{ QRect pr = paddingRect(r); if (!hasBox()) return pr; const int *p = box()->paddings; return pr.adjusted(p[LeftEdge], p[TopEdge], -p[RightEdge], -p[BottomEdge]);}QRect QRenderRule::boxRect(const QRect& cr, int flags) const{ QRect r = cr; if (hasBox()) { if (flags & Margin) { const int *m = box()->margins; r.adjust(-m[LeftEdge], -m[TopEdge], m[RightEdge], m[BottomEdge]); } if (flags & Padding) { const int *p = box()->paddings; r.adjust(-p[LeftEdge], -p[TopEdge], p[RightEdge], p[BottomEdge]); } } if (hasBorder() && (flags & Border)) { const int *b = border()->borders; r.adjust(-b[LeftEdge], -b[TopEdge], b[RightEdge], b[BottomEdge]); } return r;}QSize QRenderRule::boxSize(const QSize &cs, int flags) const{ QSize bs = boxRect(QRect(QPoint(0, 0), cs), flags).size(); if (cs.width() < 0) bs.setWidth(-1); if (cs.height() < 0) bs.setHeight(-1); return bs;}void QRenderRule::fixupBorder(int nativeWidth){ if (bd == 0) return; if (!bd->hasBorderImage() || bd->bi->pixmap.isNull()) { bd->bi = 0; // ignore the color, border of edges that have none border-style QBrush color = pal ? pal->foreground : QBrush(); const bool hasRadius = bd->radii[0].isValid() || bd->radii[1].isValid() || bd->radii[2].isValid() || bd->radii[3].isValid(); for (int i = 0; i < 4; i++) { if ((bd->styles[i] == BorderStyle_Native) && hasRadius) bd->styles[i] = BorderStyle_None; switch (bd->styles[i]) { case BorderStyle_None: // border-style: none forces width to be 0 bd->colors[i] = QBrush(); bd->borders[i] = 0; break; case BorderStyle_Native: if (bd->borders[i] == 0) bd->borders[i] = nativeWidth; // intentional fall through default: if (!bd->colors[i].style() != Qt::NoBrush) // auto-acquire 'color' bd->colors[i] = color; break; } } return; } // inspect the border image QStyleSheetBorderImageData *bi = bd->bi; if (bi->cuts[0] == -1) { for (int i = 0; i < 4; i++) // assume, cut = border bi->cuts[i] = int(border()->borders[i]); } bi->cutBorderImage();}void QStyleSheetBorderImageData::cutBorderImage(){ const int w = pixmap.width(); const int h = pixmap.height(); const int &l = cuts[LeftEdge], &r = cuts[RightEdge], &t = cuts[TopEdge], &b = cuts[BottomEdge]; topEdgeRect = QRect(l, 0, w - r - l, t); bottomEdgeRect = QRect(l, h - b, w - l - r, b); if (horizStretch != TileMode_Stretch) { if (topEdgeRect.isValid()) topEdge = pixmap.copy(topEdgeRect).scaledToHeight(t); if (bottomEdgeRect.isValid()) bottomEdge = pixmap.copy(bottomEdgeRect).scaledToHeight(b); } leftEdgeRect = QRect(0, t, l, h - b - t); rightEdgeRect = QRect(w - r, t, r, h - t- b); if (vertStretch != TileMode_Stretch) { if (leftEdgeRect.isValid()) leftEdge = pixmap.copy(leftEdgeRect).scaledToWidth(l); if (rightEdgeRect.isValid()) rightEdge = pixmap.copy(rightEdgeRect).scaledToWidth(r); } middleRect = QRect(l, t, w - r -l, h - t - b); if (middleRect.isValid() && !(horizStretch == TileMode_Stretch && vertStretch == TileMode_Stretch)) { middle = pixmap.copy(middleRect); }}// Determines if Edge e1 draws over Edge e2. Depending on this trapezoids or rectanges are drawnbool QRenderRule::paintsOver(Edge e1, Edge e2){ BorderStyle s1 = bd->styles[e1]; BorderStyle s2 = bd->styles[e2]; if (s2 == BorderStyle_None || bd->colors[e2] == Qt::transparent) return true; if ((s1 == BorderStyle_Solid && s2 == BorderStyle_Solid) && (bd->colors[e1] == bd->colors[e2])) return true; return false;}static void qDrawCenterTiledPixmap(QPainter *p, const QRectF& r, const QPixmap& pix){ p->drawTiledPixmap(r, pix, QPoint(pix.width() - int(r.width())%pix.width(), pix.height() - int(r.height())%pix.height()));}// Note: Round is not supportedvoid QRenderRule::drawBorderImage(QPainter *p, const QRect& rect){ setClip(p, rect); const QRectF br(rect); const int *borders = border()->borders; const int &l = borders[LeftEdge], &r = borders[RightEdge], &t = borders[TopEdge], &b = borders[BottomEdge]; QRectF pr = br.adjusted(l, t, -r, -b); bool wasSmoothPixmapTransform = p->renderHints() & QPainter::SmoothPixmapTransform; p->setRenderHint(QPainter::SmoothPixmapTransform); const QStyleSheetBorderImageData *bi = border()->borderImage(); const QPixmap& pix = bi->pixmap; const int *c = bi->cuts; QRectF tlc(0, 0, c[LeftEdge], c[TopEdge]); if (tlc.isValid()) p->drawPixmap(QRectF(br.topLeft(), QSizeF(l, t)), pix, tlc); QRectF trc(pix.width() - c[RightEdge], 0, c[RightEdge], c[TopEdge]); if (trc.isValid()) p->drawPixmap(QRectF(br.left() + br.width() - r, br.y(), r, t), pix, trc); QRectF blc(0, pix.height() - c[BottomEdge], c[LeftEdge], c[BottomEdge]); if (blc.isValid()) p->drawPixmap(QRectF(br.x(), br.y() + br.height() - b, l, b), pix, blc); QRectF brc(pix.width() - c[RightEdge], pix.height() - c[BottomEdge], c[RightEdge], c[BottomEdge]); if (brc.isValid()) p->drawPixmap(QRectF(br.x() + br.width() - r, br.y() + br.height() - b, r, b), pix, brc); QRectF topEdgeRect(br.x() + l, br.y(), pr.width(), t); QRectF bottomEdgeRect(br.x() + l, br.y() + br.height() - b, pr.width(), b); switch (bi->horizStretch) { case TileMode_Stretch: if (bi->topEdgeRect.isValid()) p->drawPixmap(topEdgeRect, pix, bi->topEdgeRect); if (bi->bottomEdgeRect.isValid()) p->drawPixmap(bottomEdgeRect, pix, bi->bottomEdgeRect); if (bi->middleRect.isValid()) { if (bi->vertStretch == TileMode_Stretch) p->drawPixmap(pr, pix, bi->middleRect); else if (bi->vertStretch == TileMode_Repeat) { QPixmap scaled = bi->middle.scaled(int(pr.width()), bi->middle.height()); qDrawCenterTiledPixmap(p, pr, scaled); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -