📄 q3richtext.cpp
字号:
curtag = tags.pop(); } /* special handling for p and li for HTML compatibility. We do not want to embed blocks in p, and we do not want new blocks inside non-empty lis. Plus we want to merge empty lis sometimes. */ if(nstyle->displayMode() == Q3StyleSheetItem::DisplayListItem) { canMergeLi = true; } else if (nstyle->displayMode() == Q3StyleSheetItem::DisplayBlock) { while (curtag.style->name() == "p") { if (tags.isEmpty()) break; curtag = tags.pop(); } if (curtag.style->displayMode() == Q3StyleSheetItem::DisplayListItem) { // we are in a li and a new block comes along if (nstyle->name() == "ul" || nstyle->name() == "ol") hasNewPar = false; // we want an empty li (like most browsers) if (!hasNewPar) { /* do not add new blocks inside non-empty lis */ while (curtag.style->displayMode() == Q3StyleSheetItem::DisplayListItem) { if (tags.isEmpty()) break; curtag = tags.pop(); } } else if (canMergeLi) { /* we have an empty li and a block comes along, merge them */ nstyle = curtag.style; } canMergeLi = false; } } }#ifndef QT_NO_TEXTCUSTOMITEM Q3TextCustomItem* custom = 0;#else bool custom = false;#endif // some well-known tags, some have a nstyle, some not if (wellKnownTags.contains(tagname)) { if (tagname == "br") { emptyTag = space = true; int index = qMax(curpar->length(),1) - 1; Q3TextFormat format = curtag.format.makeTextFormat(nstyle, attr, scaleFontsFactor); curpar->append(QString(QChar(QChar::LineSeparator))); curpar->setFormat(index, 1, &format); hasNewPar = false; } else if (tagname == "hr") { emptyTag = space = true;#ifndef QT_NO_TEXTCUSTOMITEM custom = tag(sheet_, tagname, attr, contxt, *factory_ , emptyTag, this);#endif } else if (tagname == "table") { emptyTag = space = true;#ifndef QT_NO_TEXTCUSTOMITEM Q3TextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor); curpar->setAlignment(curtag.alignment); custom = parseTable(attr, format, doc, length, pos, curpar);#endif } else if (tagname == "qt" || tagname == "body") { it = attr.find("bgcolor"); if (it != end) { QBrush *b = new QBrush(QColor(*it)); setPaper(b); } it = attr.find("background"); if (it != end) {#ifndef QT_NO_MIME QImage img; QString bg = *it; const QMimeSource* m = factory_->data(bg, contxt); if (!m) { qCritical("QRichText: no mimesource for %s", QFile::encodeName(bg).data()); } else { if (!Q3ImageDrag::decode(m, img)) { qCritical("Q3TextImage: cannot decode %s", QFile::encodeName(bg).data()); } } if (!img.isNull()) { QBrush *b = new QBrush(QColor(), QPixmap(img)); setPaper(b); }#endif } it = attr.find("text"); if (it != end) { QColor c(*it); initag.format.setColor(c); curtag.format.setColor(c); bodyText = c; } it = attr.find("link"); if (it != end) linkColor = QColor(*it); it = attr.find("title"); if (it != end) attribs.insert("title", *it); if (textEditMode) { it = attr.find("style"); if (it != end) { QString a = *it; int count = a.count(';') + 1; for (int s = 0; s < count; s++) { QString style = a.section(';', s, s); if (style.startsWith("font-size:") && style.endsWith("pt")) { scaleFontsFactor = double(formatCollection()->defaultFormat()->fn.pointSize()) / style.mid(10, style.length() - 12).toInt(); } } } nstyle = 0; // ignore body in textEditMode } // end qt- and body-tag handling } else if (tagname == "meta") { if (attr["name"] == "qrichtext" && attr["content"] == "1") textEditMode = true; } else if (tagname == "title") { QString title; while (pos < length) { if (hasPrefix(doc, length, pos, QChar('<')) && hasPrefix(doc, length, pos+1, QChar('/')) && parseCloseTag(doc, length, pos) == "title") break; title += doc[pos]; ++pos; } attribs.insert("title", title); } } // end of well-known tag handling#ifndef QT_NO_TEXTCUSTOMITEM if (!custom) // try generic custom item custom = tag(sheet_, tagname, attr, contxt, *factory_ , emptyTag, this);#endif if (!nstyle && !custom) // we have no clue what this tag could be, ignore it continue; if (custom) {#ifndef QT_NO_TEXTCUSTOMITEM int index = qMax(curpar->length(),1) - 1; Q3TextFormat format = curtag.format.makeTextFormat(nstyle, attr, scaleFontsFactor); curpar->append(QString(QChar('*'))); Q3TextFormat* f = formatCollection()->format(&format); curpar->setFormat(index, 1, f); curpar->at(index)->setCustomItem(custom); if (!curtag.anchorHref.isEmpty()) curpar->at(index)->setAnchor(QString(), curtag.anchorHref); if (!anchorName.isEmpty() ) { curpar->at(index)->setAnchor(anchorName, curpar->at(index)->anchorHref()); anchorName.clear(); } registerCustomItem(custom, curpar); hasNewPar = false;#endif } else if (!emptyTag) { /* if we do nesting, push curtag on the stack, otherwise reinint curag. */ if (curtag.style->name() != tagname || nstyle->selfNesting()) { tags.push(curtag); } else { if (!tags.isEmpty()) curtag = tags.top(); else curtag = initag; } curtag.name = tagname; curtag.style = nstyle; curtag.name = tagname; curtag.style = nstyle; if (nstyle->whiteSpaceMode() != Q3StyleSheetItem::WhiteSpaceModeUndefined) curtag.wsm = nstyle->whiteSpaceMode(); /* netscape compatibility: eat a newline and only a newline if a pre block starts */ if (curtag.wsm == Q3StyleSheetItem::WhiteSpacePre && nstyle->displayMode() == Q3StyleSheetItem::DisplayBlock) eat(doc, length, pos, '\n'); /* ignore whitespace for inline elements if there was already one*/ if (!textEditMode && (curtag.wsm == Q3StyleSheetItem::WhiteSpaceNormal || curtag.wsm == Q3StyleSheetItem::WhiteSpaceNoWrap) && (space || nstyle->displayMode() != Q3StyleSheetItem::DisplayInline)) eatSpace(doc, length, pos); curtag.format = curtag.format.makeTextFormat(nstyle, attr, scaleFontsFactor); if (nstyle->isAnchor()) { if (!anchorName.isEmpty()) anchorName += "#" + attr["name"]; else anchorName = attr["name"]; curtag.anchorHref = attr["href"]; } if (nstyle->alignment() != Q3StyleSheetItem::Undefined) curtag.alignment = nstyle->alignment(); if (nstyle->listStyle() != Q3StyleSheetItem::ListStyleUndefined) curtag.liststyle = nstyle->listStyle(); if (nstyle->displayMode() == Q3StyleSheetItem::DisplayBlock || nstyle->displayMode() == Q3StyleSheetItem::DisplayListItem) { if (nstyle->name() == "ol" || nstyle->name() == "ul" || nstyle->name() == "li") { QString type = attr["type"]; if (!type.isEmpty()) { if (type == "1") { curtag.liststyle = Q3StyleSheetItem::ListDecimal; } else if (type == "a") { curtag.liststyle = Q3StyleSheetItem::ListLowerAlpha; } else if (type == "A") { curtag.liststyle = Q3StyleSheetItem::ListUpperAlpha; } else { type = type.toLower(); if (type == "square") curtag.liststyle = Q3StyleSheetItem::ListSquare; else if (type == "disc") curtag.liststyle = Q3StyleSheetItem::ListDisc; else if (type == "circle") curtag.liststyle = Q3StyleSheetItem::ListCircle; } } } /* Internally we treat ordered and bullet lists the same for margin calculations. In order to have fast pointer compares in the xMargin() functions we restrict ourselves to <ol>. Once we calculate the margins in the parser rathern than later, the unelegance of this approach goes awy */ if (nstyle->name() == "ul") curtag.style = sheet_->item("ol"); it = attr.find("align"); if (it != end) { QString align = (*it).toLower(); if (align == "center") curtag.alignment = Qt::AlignCenter; else if (align == "right") curtag.alignment = Qt::AlignRight; else if (align == "justify") curtag.alignment = Qt::AlignJustify; } it = attr.find("dir"); if (it != end) { QString dir = (*it).toLower(); if (dir == "rtl") curtag.direction = QChar::DirR; else if (dir == "ltr") curtag.direction = QChar::DirL; } NEWPAR; if (curtag.style->displayMode() == Q3StyleSheetItem::DisplayListItem) { it = attr.find("value"); if (it != end) curpar->setListValue((*it).toInt()); } it = attr.find("style"); if (it != end) { QString a = *it; bool ok = true; int count = a.count(';')+1; for (int s = 0; ok && s < count; s++) { QString style = a.section(';', s, s); if (style.startsWith("margin-top:") && style.endsWith("px")) curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok); else if (style.startsWith("margin-bottom:") && style.endsWith("px")) curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok); else if (style.startsWith("margin-left:") && style.endsWith("px")) curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok); else if (style.startsWith("margin-right:") && style.endsWith("px")) curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok); else if (style.startsWith("text-indent:") && style.endsWith("px")) curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok); } if (!ok) // be pressmistic curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0; } } } } else { QString tagname = parseCloseTag(doc, length, pos); if (tagname.isEmpty()) continue; // nothing we could do with this, probably parse error if (!sheet_->item(tagname)) // ignore unknown tags continue; if (tagname == "li") continue; // we close a block item. Since the text may continue, we need to have a new paragraph bool needNewPar = curtag.style->displayMode() == Q3StyleSheetItem::DisplayBlock || curtag.style->displayMode() == Q3StyleSheetItem::DisplayListItem; // html slopiness: handle unbalanched tag closing while (curtag.name != tagname) { QString msg; msg.sprintf("QText Warning: Document not valid ('%s' not closed before '%s' #%d)", curtag.name.ascii(), tagname.ascii(), pos); sheet_->error(msg); if (tags.isEmpty()) break; curtag = tags.pop(); } // close the tag if (!tags.isEmpty()) curtag = tags.pop(); else curtag = initag; if (needNewPar) { if (textEditMode && (tagname == "p" || tagname == "div")) // preserve empty paragraphs hasNewPar = false; NEWPAR; } } } else { // normal contents QString s; QChar c; while (pos < length && !hasPrefix(doc, length, pos, QChar('<'))){ if (textEditMode) { // text edit mode: we handle all white space but ignore newlines c = parseChar(doc, length, pos, Q3StyleSheetItem::WhiteSpacePre); if (c == QChar::LineSeparator) break; } else { int l = pos; c = parseChar(doc, length, pos, curtag.wsm); // in white space pre mode: treat any space as non breakable // and expand tabs to eight character wide columns. if (curtag.wsm == Q3StyleSheetItem::WhiteSpacePre) { if (c == '\t') { c = ' '; while((++tabExpansionColumn)%8) s += c; } if (c == QChar::LineSeparator) tabExpansionColumn = 0; else tabExpansionColumn++; } if (c == ' ' || c == QChar::LineSeparator) { /* avoid overlong paragraphs by forcing a new paragraph after 4096 characters. This case can occur when loading undiscovered plain text documents in rich text mode. Instead of hanging forever, we do the trick. */ if (curtag.wsm == Q3StyleSheetItem::WhiteSpaceNormal && s.length() > 4096) do { if (doc[l] == '\n') { hasNewPar = false; // for a new paragraph ... NEWPAR; hasNewPar = false; // ... and make it non-reusable c = '\n'; // make sure we break below break; } } while (++l < pos); } } if (c == '\n') break; // break on newlines, pre delievers a QChar::LineSeparator bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode; if (curtag.wsm == Q3StyleSheetItem::WhiteSpaceNormal && c_isSpace && space) continue; if (c == '\r') continue; space = c_isSpace; s += c; } if (!s.isEmpty() && curtag.style->displayMode() != Q3StyleSheetItem::DisplayNone) { hasNewPar = false; int index = qMax(curpar->length(),1) - 1; curpar->append(s); if (curtag.wsm != Q3StyleSheetItem::WhiteSpaceNormal) { Q3TextString *str = curpar->string(); for (int i = index; i < index + s.length(); ++i) str->at(i).nobreak = true; } Q3TextFormat* f = formatCollection()->format(&curtag.format); curpar->setFormat(index, s.length(), f, false); // do not use collection because we have done that already f->ref += s.length() -1; // that what friends are for... if (!curtag.anc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -