📄 q3richtext.cpp
字号:
}Q3TextCursor *Q3TextStyleCommand::execute(Q3TextCursor *c){ writeStyleInformation(doc, firstParag, after); return c;}Q3TextCursor *Q3TextStyleCommand::unexecute(Q3TextCursor *c){ writeStyleInformation(doc, firstParag, before); return c;}// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Q3TextCursor::Q3TextCursor(Q3TextDocument *dc) : idx(0), tmpX(-1), ox(0), oy(0), valid(true){ para = dc ? dc->firstParagraph() : 0;}Q3TextCursor::Q3TextCursor(const Q3TextCursor &c){ ox = c.ox; oy = c.oy; idx = c.idx; para = c.para; tmpX = c.tmpX; indices = c.indices; paras = c.paras; xOffsets = c.xOffsets; yOffsets = c.yOffsets; valid = c.valid;}Q3TextCursor::~Q3TextCursor(){}Q3TextCursor &Q3TextCursor::operator=(const Q3TextCursor &c){ ox = c.ox; oy = c.oy; idx = c.idx; para = c.para; tmpX = c.tmpX; indices = c.indices; paras = c.paras; xOffsets = c.xOffsets; yOffsets = c.yOffsets; valid = c.valid; return *this;}bool Q3TextCursor::operator==(const Q3TextCursor &c) const{ return para == c.para && idx == c.idx;}int Q3TextCursor::totalOffsetX() const{ int xoff = ox; for (QStack<int>::ConstIterator xit = xOffsets.begin(); xit != xOffsets.end(); ++xit) xoff += *xit; return xoff;}int Q3TextCursor::totalOffsetY() const{ int yoff = oy; for (QStack<int>::ConstIterator yit = yOffsets.begin(); yit != yOffsets.end(); ++yit) yoff += *yit; return yoff;}#ifndef QT_NO_TEXTCUSTOMITEMvoid Q3TextCursor::gotoIntoNested(const QPoint &globalPos){ if (!para) return; Q_ASSERT(para->at(idx)->isCustom()); push(); ox = 0; int bl, y; para->lineHeightOfChar(idx, &bl, &y); oy = y + para->rect().y(); ox = para->at(idx)->x; Q3TextDocument* doc = document(); para->at(idx)->customItem()->enterAt(this, doc, para, idx, ox, oy, globalPos-QPoint(ox,oy));}#endifvoid Q3TextCursor::invalidateNested(){ if (nestedDepth()) { QStack<Q3TextParagraph*>::Iterator it = paras.begin(); QStack<int>::Iterator it2 = indices.begin(); for (; it != paras.end(); ++it, ++it2) { if (*it == para) continue; (*it)->invalidate(0);#ifndef QT_NO_TEXTCUSTOMITEM if ((*it)->at(*it2)->isCustom()) (*it)->at(*it2)->customItem()->invalidate();#endif } }}void Q3TextCursor::insert(const QString &str, bool checkNewLine, QVector<Q3TextStringChar> *formatting){ tmpX = -1; bool justInsert = true; QString s(str);#if defined(Q_WS_WIN) if (checkNewLine) { int i = 0; while ((i = s.indexOf(QLatin1Char('\r'), i)) != -1) s.remove(i ,1); }#endif if (checkNewLine) justInsert = s.indexOf(QLatin1Char('\n')) == -1; if (justInsert) { // we ignore new lines and insert all in the current para at the current index para->insert(idx, s.unicode(), s.length()); if (formatting) { for (int i = 0; i < (int)s.length(); ++i) { if (formatting->at(i).format()) { formatting->at(i).format()->addRef(); para->string()->setFormat(idx + i, formatting->at(i).format(), true); } } } idx += s.length(); } else { // we split at new lines int start = -1; int end; int y = para->rect().y() + para->rect().height(); int lastIndex = 0; do { end = s.indexOf(QLatin1Char('\n'), start + 1); // find line break if (end == -1) // didn't find one, so end of line is end of string end = s.length(); int len = (start == -1 ? end : end - start - 1); if (len > 0) // insert the line para->insert(idx, s.unicode() + start + 1, len); else para->invalidate(0); if (formatting) { // set formats to the chars of the line for (int i = 0; i < len; ++i) { if (formatting->at(i + lastIndex).format()) { formatting->at(i + lastIndex).format()->addRef(); para->string()->setFormat(i + idx, formatting->at(i + lastIndex).format(), true); } } lastIndex += len; } start = end; // next start is at the end of this line idx += len; // increase the index of the cursor to the end of the inserted text if (s[end] == QLatin1Char('\n')) { // if at the end was a line break, break the line splitAndInsertEmptyParagraph(false, true); para->setEndState(-1); para->prev()->format(-1, false); lastIndex++; } } while (end < (int)s.length()); para->format(-1, false); int dy = para->rect().y() + para->rect().height() - y; Q3TextParagraph *p = para; p->setParagId(p->prev() ? p->prev()->paragId() + 1 : 0); p = p->next(); while (p) { p->setParagId(p->prev()->paragId() + 1); p->move(dy); p->invalidate(0); p->setEndState(-1); p = p->next(); } } int h = para->rect().height(); para->format(-1, true); if (h != para->rect().height()) invalidateNested(); else if (para->document() && para->document()->parent()) para->document()->nextDoubleBuffered = true; fixCursorPosition();}void Q3TextCursor::gotoLeft(){ if (para->string()->isRightToLeft()) gotoNextLetter(); else gotoPreviousLetter();}void Q3TextCursor::gotoPreviousLetter(){ tmpX = -1; if (idx > 0) { idx = para->string()->previousCursorPosition(idx);#ifndef QT_NO_TEXTCUSTOMITEM const Q3TextStringChar *tsc = para->at(idx); if (tsc && tsc->isCustom() && tsc->customItem()->isNested()) processNesting(EnterEnd);#endif } else if (para->prev()) { para = para->prev(); while (!para->isVisible() && para->prev()) para = para->prev(); idx = para->length() - 1; } else if (nestedDepth()) { pop(); processNesting(Prev); if (idx == -1) { pop(); if (idx > 0) { idx = para->string()->previousCursorPosition(idx);#ifndef QT_NO_TEXTCUSTOMITEM const Q3TextStringChar *tsc = para->at(idx); if (tsc && tsc->isCustom() && tsc->customItem()->isNested()) processNesting(EnterEnd);#endif } else if (para->prev()) { para = para->prev(); idx = para->length() - 1; } } }}void Q3TextCursor::push(){ indices.push(idx); paras.push(para); xOffsets.push(ox); yOffsets.push(oy);}void Q3TextCursor::pop(){ if (indices.isEmpty()) return; idx = indices.pop(); para = paras.pop(); ox = xOffsets.pop(); oy = yOffsets.pop();}void Q3TextCursor::restoreState(){ while (!indices.isEmpty()) pop();}bool Q3TextCursor::place(const QPoint &p, Q3TextParagraph *s, bool link){ QPoint pos(p); QRect r; Q3TextParagraph *str = s; if (pos.y() < s->rect().y()) { pos.setY(s->rect().y());#ifdef Q_WS_MAC pos.setX(s->rect().x());#endif } while (s) { r = s->rect(); r.setWidth(document() ? document()->width() : QWIDGETSIZE_MAX); if (s->isVisible()) str = s; if (pos.y() >= r.y() && pos.y() <= r.y() + r.height()) break; if (!s->next()) {#ifdef Q_WS_MAC pos.setX(s->rect().x() + s->rect().width());#endif break; } s = s->next(); } if (!s || !str) return false; s = str; setParagraph(s); int y = s->rect().y(); int lines = s->lines(); Q3TextStringChar *chr = 0; int index = 0; int i = 0; int cy = 0; int ch = 0; for (; i < lines; ++i) { chr = s->lineStartOfLine(i, &index); cy = s->lineY(i); ch = s->lineHeight(i); if (!chr) return false; if (pos.y() <= y + cy + ch) break; } int nextLine; if (i < lines - 1) s->lineStartOfLine(i+1, &nextLine); else nextLine = s->length(); i = index; int x = s->rect().x(); if (pos.x() < x) pos.setX(x + 1); int cw; int curpos = s->length()-1; int dist = 10000000; bool inCustom = false; while (i < nextLine) { chr = s->at(i); int cpos = x + chr->x; cw = s->string()->width(i);#ifndef QT_NO_TEXTCUSTOMITEM if (chr->isCustom() && chr->customItem()->isNested()) { if (pos.x() >= cpos && pos.x() <= cpos + cw && pos.y() >= y + cy && pos.y() <= y + cy + chr->height()) { inCustom = true; curpos = i; break; } } else#endif { if(chr->rightToLeft) cpos += cw; int diff = cpos - pos.x(); bool dm = diff < 0 ? !chr->rightToLeft : chr->rightToLeft; if ((QABS(diff) < dist || (dist == diff && dm == true)) && para->string()->validCursorPosition(i)) { dist = QABS(diff); if (!link || pos.x() >= x + chr->x) curpos = i; } } i++; } setIndex(curpos);#ifndef QT_NO_TEXTCUSTOMITEM if (inCustom && para->document() && para->at(curpos)->isCustom() && para->at(curpos)->customItem()->isNested()) { Q3TextDocument *oldDoc = para->document(); gotoIntoNested(pos); if (oldDoc == para->document()) return true; QPoint p(pos.x() - offsetX(), pos.y() - offsetY()); if (!place(p, document()->firstParagraph(), link)) pop(); }#endif return true;}bool Q3TextCursor::processNesting(Operation op){ if (!para->document()) return false; Q3TextDocument* doc = para->document(); push(); ox = para->at(idx)->x; int bl, y; para->lineHeightOfChar(idx, &bl, &y); oy = y + para->rect().y(); bool ok = false;#ifndef QT_NO_TEXTCUSTOMITEM switch (op) { case EnterBegin: ok = para->at(idx)->customItem()->enter(this, doc, para, idx, ox, oy); break; case EnterEnd: ok = para->at(idx)->customItem()->enter(this, doc, para, idx, ox, oy, true); break; case Next: ok = para->at(idx)->customItem()->next(this, doc, para, idx, ox, oy); break; case Prev: ok = para->at(idx)->customItem()->prev(this, doc, para, idx, ox, oy); break; case Down: ok = para->at(idx)->customItem()->down(this, doc, para, idx, ox, oy); break; case Up: ok = para->at(idx)->customItem()->up(this, doc, para, idx, ox, oy); break; } if (!ok)#endif pop();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -