📄 q3richtext.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the Qt3Support module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "q3richtext_p.h"#ifndef QT_NO_RICHTEXT#include "qbitmap.h"#include "qapplication.h"#include "q3cleanuphandler.h"#include "qcursor.h"#include "qdatastream.h"#include "q3dragobject.h"#include "qdrawutil.h"#include "qfile.h"#include "qfileinfo.h"#include "qfont.h"#include "qimage.h"#include "qmap.h"#include "qmime.h"#include "q3paintdevicemetrics.h"#include "qpainter.h"#include "qstringlist.h"#include "qstyle.h"#include "qstyleoption.h"#include "q3stylesheet.h"#include "qtextstream.h"#include <private/qtextengine_p.h>#include <private/qunicodetables_p.h>#include <stdlib.h>#if defined(Q_WS_X11)#include "qx11info_x11.h"#endifstatic Q3TextCursor* richTextExportStart = 0;static Q3TextCursor* richTextExportEnd = 0;class Q3TextFormatCollection;const int border_tolerance = 2;#ifdef Q_WS_WIN#include "qt_windows.h"#endifstatic inline bool is_printer(QPainter *p){ if (!p || !p->device()) return false; return p->device()->devType() == QInternal::Printer;}static inline int scale(int value, QPainter *painter){ if (is_printer(painter)) { Q3PaintDeviceMetrics metrics(painter->device());#if defined(Q_WS_X11) value = value * metrics.logicalDpiY() / QX11Info::appDpiY(painter->device()->x11Screen());#elif defined (Q_WS_WIN) HDC hdc = GetDC(0); int gdc = GetDeviceCaps(hdc, LOGPIXELSY); if (gdc) value = value * metrics.logicalDpiY() / gdc; ReleaseDC(0, hdc);#elif defined (Q_WS_MAC) value = value * metrics.logicalDpiY() / 75; // ##### FIXME#elif defined (Q_WS_QWS) value = value * metrics.logicalDpiY() / 75;#endif } return value;}static inline bool isBreakable(Q3TextString *string, int pos){ if (string->at(pos).nobreak) return false; return (pos < string->length()-1 && string->at(pos+1).softBreak);}// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++void Q3TextCommandHistory::addCommand(Q3TextCommand *cmd){ if (current < history.count() - 1) { QList<Q3TextCommand *> commands; for (int i = 0; i <= current; ++i) commands.insert(i, history.takeFirst()); commands.append(cmd); while (!history.isEmpty()) delete history.takeFirst(); history = commands; } else { history.append(cmd); } if (history.count() > steps) delete history.takeFirst(); else ++current;}Q3TextCursor *Q3TextCommandHistory::undo(Q3TextCursor *c){ if (current > -1) { Q3TextCursor *c2 = history.at(current)->unexecute(c); --current; return c2; } return 0;}Q3TextCursor *Q3TextCommandHistory::redo(Q3TextCursor *c){ if (current > -1) { if (current < history.count() - 1) { ++current; return history.at(current)->execute(c); } } else { if (history.count() > 0) { ++current; return history.at(current)->execute(c); } } return 0;}bool Q3TextCommandHistory::isUndoAvailable(){ return current > -1;}bool Q3TextCommandHistory::isRedoAvailable(){ return current > -1 && current < history.count() - 1 || current == -1 && history.count() > 0;}// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Q3TextDeleteCommand::Q3TextDeleteCommand(Q3TextDocument *dc, int i, int idx, const QVector<Q3TextStringChar> &str, const QByteArray& oldStyleInfo) : Q3TextCommand(dc), id(i), index(idx), parag(0), text(str), styleInformation(oldStyleInfo){ for (int j = 0; j < (int)text.size(); ++j) { if (text[j].format()) text[j].format()->addRef(); }}Q3TextDeleteCommand::Q3TextDeleteCommand(Q3TextParagraph *p, int idx, const QVector<Q3TextStringChar> &str) : Q3TextCommand(0), id(-1), index(idx), parag(p), text(str){ for (int i = 0; i < (int)text.size(); ++i) { if (text[i].format()) text[i].format()->addRef(); }}Q3TextDeleteCommand::~Q3TextDeleteCommand(){ for (int i = 0; i < (int)text.size(); ++i) { if (text[i].format()) text[i].format()->removeRef(); } text.resize(0);}Q3TextCursor *Q3TextDeleteCommand::execute(Q3TextCursor *c){ Q3TextParagraph *s = doc ? doc->paragAt(id) : parag; if (!s) { qWarning("can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId()); return 0; } cursor.setParagraph(s); cursor.setIndex(index); int len = text.size(); if (c) *c = cursor; if (doc) { doc->setSelectionStart(Q3TextDocument::Temp, cursor); for (int i = 0; i < len; ++i) cursor.gotoNextLetter(); doc->setSelectionEnd(Q3TextDocument::Temp, cursor); doc->removeSelectedText(Q3TextDocument::Temp, &cursor); if (c) *c = cursor; } else { s->remove(index, len); } return c;}Q3TextCursor *Q3TextDeleteCommand::unexecute(Q3TextCursor *c){ Q3TextParagraph *s = doc ? doc->paragAt(id) : parag; if (!s) { qWarning("can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId()); return 0; } cursor.setParagraph(s); cursor.setIndex(index); QString str = Q3TextString::toString(text); cursor.insert(str, true, &text); if (c) *c = cursor; cursor.setParagraph(s); cursor.setIndex(index);#ifndef QT_NO_DATASTREAM if (!styleInformation.isEmpty()) { QDataStream styleStream(&styleInformation, IO_ReadOnly); int num; styleStream >> num; Q3TextParagraph *p = s; while (num-- && p) { p->readStyleInformation(styleStream); p = p->next(); } }#endif s = cursor.paragraph(); while (s) { s->format(); s->setChanged(true); if (s == c->paragraph()) break; s = s->next(); } return &cursor;}Q3TextFormatCommand::Q3TextFormatCommand(Q3TextDocument *dc, int sid, int sidx, int eid, int eidx, const QVector<Q3TextStringChar> &old, Q3TextFormat *f, int fl) : Q3TextCommand(dc), startId(sid), startIndex(sidx), endId(eid), endIndex(eidx), format(f), oldFormats(old), flags(fl){ format = dc->formatCollection()->format(f); for (int j = 0; j < (int)oldFormats.size(); ++j) { if (oldFormats[j].format()) oldFormats[j].format()->addRef(); }}Q3TextFormatCommand::~Q3TextFormatCommand(){ format->removeRef(); for (int j = 0; j < (int)oldFormats.size(); ++j) { if (oldFormats[j].format()) oldFormats[j].format()->removeRef(); }}Q3TextCursor *Q3TextFormatCommand::execute(Q3TextCursor *c){ Q3TextParagraph *sp = doc->paragAt(startId); Q3TextParagraph *ep = doc->paragAt(endId); if (!sp || !ep) return c; Q3TextCursor start(doc); start.setParagraph(sp); start.setIndex(startIndex); Q3TextCursor end(doc); end.setParagraph(ep); end.setIndex(endIndex); doc->setSelectionStart(Q3TextDocument::Temp, start); doc->setSelectionEnd(Q3TextDocument::Temp, end); doc->setFormat(Q3TextDocument::Temp, format, flags); doc->removeSelection(Q3TextDocument::Temp); if (endIndex == ep->length()) end.gotoLeft(); *c = end; return c;}Q3TextCursor *Q3TextFormatCommand::unexecute(Q3TextCursor *c){ Q3TextParagraph *sp = doc->paragAt(startId); Q3TextParagraph *ep = doc->paragAt(endId); if (!sp || !ep) return 0; int idx = startIndex; int fIndex = 0; while ( fIndex < int(oldFormats.size()) ) { if (oldFormats.at(fIndex).c == QLatin1Char('\n')) { if (idx > 0) { if (idx < sp->length() && fIndex > 0) sp->setFormat(idx, 1, oldFormats.at(fIndex - 1).format()); if (sp == ep) break; sp = sp->next(); idx = 0; } fIndex++; } if (oldFormats.at(fIndex).format()) sp->setFormat(idx, 1, oldFormats.at(fIndex).format()); idx++; fIndex++; if (fIndex >= (int)oldFormats.size()) break; if (idx >= sp->length()) { if (sp == ep) break; sp = sp->next(); idx = 0; } } Q3TextCursor end(doc); end.setParagraph(ep); end.setIndex(endIndex); if (endIndex == ep->length()) end.gotoLeft(); *c = end; return c;}Q3TextStyleCommand::Q3TextStyleCommand(Q3TextDocument *dc, int fParag, int lParag, const QByteArray& beforeChange) : Q3TextCommand(dc), firstParag(fParag), lastParag(lParag), before(beforeChange){ after = readStyleInformation( dc, fParag, lParag);}QByteArray Q3TextStyleCommand::readStyleInformation( Q3TextDocument* doc, int fParag, int lParag){ QByteArray style;#ifndef QT_NO_DATASTREAM Q3TextParagraph *p = doc->paragAt(fParag); if (!p) return style; QDataStream styleStream(&style, IO_WriteOnly); int num = lParag - fParag + 1; styleStream << num; while (num -- && p) { p->writeStyleInformation(styleStream); p = p->next(); }#endif return style;}void Q3TextStyleCommand::writeStyleInformation( Q3TextDocument* doc, int fParag, const QByteArray& style){#ifndef QT_NO_DATASTREAM Q3TextParagraph *p = doc->paragAt(fParag); if (!p) return; QByteArray copy = style; QDataStream styleStream(©, IO_ReadOnly); int num; styleStream >> num; while (num-- && p) { p->readStyleInformation(styleStream); p = p->next(); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -