📄 q3richtext.cpp
字号:
cursor->splitAndInsertEmptyParagraph(); Q3TextCursor tmp = *cursor; tmp.gotoPreviousLetter(); stylesPar = curpar = tmp.paragraph(); hasNewPar = true; textEditMode = true; } else { NEWPAR; } // set rtext spacing to false for the initial paragraph. curpar->rtext = false; QString wellKnownTags = QLatin1String("br hr wsp table qt body meta title"); while (pos < length) { if (hasPrefix(doc, length, pos, QLatin1Char('<'))){ if (!hasPrefix(doc, length, pos+1, QLatin1Char('/'))) { // open tag QMap<QString, QString> attr; QMap<QString, QString>::Iterator it, end = attr.end(); bool emptyTag = false; QString tagname = parseOpenTag(doc, length, pos, attr, emptyTag); if (tagname.isEmpty()) continue; // nothing we could do with this, probably parse error const Q3StyleSheetItem* nstyle = sheet_->item(tagname); if (nstyle) { // we might have to close some 'forgotten' tags while (!nstyle->allowedInContext(curtag.style)) { QString msg; msg.sprintf("QText Warning: Document not valid ('%s' not allowed in '%s' #%d)", tagname.ascii(), curtag.style->name().ascii(), pos); sheet_->error(msg); if (tags.isEmpty()) break; 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() == QLatin1String("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() == QString(QLatin1String("ul")) || nstyle->name() == QLatin1String("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 == QLatin1String("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 == QLatin1String("hr")) { emptyTag = space = true;#ifndef QT_NO_TEXTCUSTOMITEM custom = tag(sheet_, tagname, attr, contxt, *factory_ , emptyTag, this);#endif } else if (tagname == QLatin1String("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 == QLatin1String("qt") || tagname == QLatin1String("body")) { it = attr.find(QLatin1String("bgcolor")); if (it != end) { QBrush *b = new QBrush(QColor(*it)); setPaper(b); } it = attr.find(QLatin1String("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(QLatin1String("text")); if (it != end) { QColor c(*it); initag.format.setColor(c); curtag.format.setColor(c); bodyText = c; } it = attr.find(QLatin1String("link")); if (it != end) linkColor = QColor(*it); it = attr.find(QLatin1String("title")); if (it != end) attribs.insert(QLatin1String("title"), *it); if (textEditMode) { it = attr.find(QLatin1String("style")); if (it != end) { QString a = *it; int count = a.count(QLatin1Char(';')) + 1; for (int s = 0; s < count; s++) { QString style = a.section(QLatin1Char(';'), s, s); if (style.startsWith(QLatin1String("font-size:")) && style.endsWith(QLatin1String("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 == QLatin1String("meta")) { if (attr[QLatin1String("name")] == QLatin1String("qrichtext") && attr[QLatin1String("content")] == QLatin1String("1")) textEditMode = true; } else if (tagname == QLatin1String("title")) { QString title; while (pos < length) { if (hasPrefix(doc, length, pos, QLatin1Char('<')) && hasPrefix(doc, length, pos+1, QLatin1Char('/')) && parseCloseTag(doc, length, pos) == QLatin1String("title")) break; title += doc[pos]; ++pos; } attribs.insert(QLatin1String("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(QLatin1Char('*'))); 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, QLatin1Char('\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 += QLatin1String("#") + attr[QLatin1String("name")]; else anchorName = attr[QLatin1String("name")]; curtag.anchorHref = attr[QLatin1String("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() == QLatin1String("ol") || nstyle->name() == QLatin1String("ul") || nstyle->name() == QLatin1String("li")) { QString type = attr[QLatin1String("type")]; if (!type.isEmpty()) { if (type == QLatin1String("1")) { curtag.liststyle = Q3StyleSheetItem::ListDecimal; } else if (type == QLatin1String("a")) { curtag.liststyle = Q3StyleSheetItem::ListLowerAlpha; } else if (type == QLatin1String("A")) { curtag.liststyle = Q3StyleSheetItem::ListUpperAlpha; } else { type = type.toLower(); if (type == QLatin1String("square")) curtag.liststyle = Q3StyleSheetItem::ListSquare; else if (type == QLatin1String("disc")) curtag.liststyle = Q3StyleSheetItem::ListDisc; else if (type == QLatin1String("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() == QLatin1String("ul")) curtag.style = sheet_->item(QLatin1String("ol")); it = attr.find(QLatin1String("align")); if (it != end) { QString align = (*it).toLower(); if (align == QLatin1String("center")) curtag.alignment = Qt::AlignCenter; else if (align == QLatin1String("right")) curtag.alignment = Qt::AlignRight; else if (align == QLatin1String("justify")) curtag.alignment = Qt::AlignJustify; } it = attr.find(QLatin1String("dir")); if (it != end) { QString dir = (*it).toLower(); if (dir == QLatin1String("rtl")) curtag.direction = QChar::DirR; else if (dir == QLatin1String("ltr")) curtag.direction = QChar::DirL; } NEWPAR; if (curtag.style && curtag.style->displayMode() == Q3StyleSheetItem::DisplayListItem) { it = attr.find(QLatin1String("value")); if (it != end) curpar->setListValue((*it).toInt()); } it = attr.find(QLatin1String("style")); if (it != end) { QString a = *it; bool ok = true; int count = a.count(QLatin1Char(';'))+1; for (int s = 0; ok && s < count; s++) { QString style = a.section(QLatin1Char(';'), s, s); if (style.startsWith(QLatin1String("margin-top:")) && style.endsWith(QLatin1String("px"))) curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok); else if (style.startsWith(QLatin1String("margin-bottom:")) && style.endsWith(QLatin1String("px"))) curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok); else if (style.startsWith(QLatin1String("margin-left:")) && style.endsWith(QLatin1String("px"))) curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok); else if (style.startsWith(QLatin1String("margin-right:")) && style.endsWith(QLatin1String("px"))) curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok); else if (style.startsWith(QLatin1String("text-indent:")) && style.endsWith(QLatin1String("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 == QLatin1String("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 == QLatin1String("p") || tagname == QLatin1String("div"))) // preserve empty paragraphs hasNewPar = false; NEWPAR; } } } else { // normal contents QString s; QChar c; while (pos < length && !hasPrefix(doc, length, pos, QLatin1Char('<'))){ 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 == QLatin1Char('\t')) { c = QLatin1Char(' '); while((++tabExpansionColumn)%8) s += c; } if (c == QChar::LineSeparator) tabExpansionColumn = 0; else tabExpansionColumn++; } if (c == QLatin1Char(' ') || c == QChar::LineSeparator)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -