📄 qtextedit.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui 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://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** 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 "qtextedit.h"#include "qtextedit_p.h"#include "qlineedit.h"#ifndef QT_NO_TEXTEDIT#include <qfont.h>#include <qpainter.h>#include <qevent.h>#include <qdebug.h>#include <qmime.h>#include <qdrag.h>#include <qclipboard.h>#include <qmenu.h>#include <qstyle.h>#include <qtimer.h>#include "private/qtextdocumentlayout_p.h"#include "qtextdocument.h"#include "qtextlist.h"#include <qtextformat.h>#include <qdatetime.h>#include <qapplication.h>#include <limits.h>#include <qtexttable.h>#include <qvariant.h>#include <qurl.h>#include <qinputcontext.h>#ifndef QT_NO_SHORTCUT#include <qkeysequence.h>#define ACCEL_KEY(k) "\t" + QString(QKeySequence( Qt::CTRL | Qt::Key_ ## k ))#else#define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k)#endifclass QTextEditMimeData : public QMimeData{public: inline QTextEditMimeData(const QTextDocumentFragment &aFragment) : fragment(aFragment) {} virtual QStringList formats() const;protected: virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type) const;private: void setup() const; mutable QTextDocumentFragment fragment;};QStringList QTextEditMimeData::formats() const{ if (!fragment.isEmpty()) return QStringList() << "text/plain" << "text/html"; else return QMimeData::formats();}QVariant QTextEditMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const{ if (!fragment.isEmpty()) setup(); return QMimeData::retrieveData(mimeType, type);}void QTextEditMimeData::setup() const{ QTextEditMimeData *that = const_cast<QTextEditMimeData *>(this); QString html = fragment.toHtml(); html.replace("<head>", "<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"); that->setData(QLatin1String("text/html"), html.toUtf8()); that->setText(fragment.toPlainText()); fragment = QTextDocumentFragment();}// could go into QTextCursor...static QTextLine currentTextLine(const QTextCursor &cursor){ const QTextBlock block = cursor.block(); if (!block.isValid()) return QTextLine(); const QTextLayout *layout = block.layout(); if (!layout) return QTextLine(); const int relativePos = cursor.position() - block.position(); return layout->lineForTextPosition(relativePos);}bool QTextEditPrivate::cursorMoveKeyEvent(QKeyEvent *e){ Q_Q(QTextEdit); if (cursor.isNull()) return false; QTextCursor::MoveMode mode = e->modifiers() & Qt::ShiftModifier ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor; QTextCursor::MoveOperation op = QTextCursor::NoMove;#ifdef Q_WS_MAC // There can be only one modifier (+ shift), but we also need to make sure // that we have a "move key" pressed before we reject it. bool twoModifiers = ((e->modifiers() & (Qt::ControlModifier | Qt::AltModifier)) == (Qt::ControlModifier | Qt::AltModifier)) || ((e->modifiers() & (Qt::ControlModifier | Qt::MetaModifier)) == (Qt::ControlModifier | Qt::MetaModifier)) || ((e->modifiers() & (Qt::AltModifier | Qt::MetaModifier)) == (Qt::AltModifier | Qt::MetaModifier));#else if (e->modifiers() & (Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier)) { e->ignore(); return false; }#endif switch (e->key()) {#ifndef Q_WS_MAC // Use the default Windows bindings. case Qt::Key_Up: op = QTextCursor::Up; break; case Qt::Key_Down: op = QTextCursor::Down; if (mode == QTextCursor::KeepAnchor) { QTextBlock block = cursor.block(); QTextLine line = currentTextLine(cursor); if (!block.next().isValid() && line.isValid() && line.lineNumber() == block.layout()->lineCount() - 1) op = QTextCursor::End; } break; case Qt::Key_Left: op = e->modifiers() & Qt::ControlModifier ? QTextCursor::WordLeft : QTextCursor::Left; break; case Qt::Key_Right: op = e->modifiers() & Qt::ControlModifier ? QTextCursor::WordRight : QTextCursor::Right; break; case Qt::Key_Home: op = e->modifiers() & Qt::ControlModifier ? QTextCursor::Start : QTextCursor::StartOfLine; break; case Qt::Key_End: op = e->modifiers() & Qt::ControlModifier ? QTextCursor::End : QTextCursor::EndOfLine; break;#else// Except for pageup and pagedown, Mac OS X has very different behavior, we don't do it all, but// here's the breakdown:// Shift still works as an anchor, but only one of the other keys can be down Ctrl (Command),// Alt (Option), or Meta (Control).// Command/Control + Left/Right -- Move to left or right of the line// + Up/Down -- Move to top bottom of the file. (Control doesn't move the cursor)// Option + Left/Right -- Move one word Left/right.// + Up/Down -- Begin/End of Paragraph.// Home/End Top/Bottom of file. (usually don't move the cursor, but will select) case Qt::Key_Up: if (twoModifiers) { QApplication::beep(); return true; } else { if (e->modifiers() & (Qt::ControlModifier | Qt::MetaModifier)) op = QTextCursor::Start; else if (e->modifiers() & Qt::AltModifier) op = QTextCursor::StartOfBlock; else op = QTextCursor::Up; } break; case Qt::Key_Down: if (twoModifiers) { QApplication::beep(); return true; } else { if (e->modifiers() & (Qt::ControlModifier | Qt::MetaModifier)) { op = QTextCursor::End; } else if (e->modifiers() & Qt::AltModifier) { op = QTextCursor::EndOfBlock; } else { op = QTextCursor::Down; if (mode == QTextCursor::KeepAnchor) { QTextBlock block = cursor.block(); QTextLine line = currentTextLine(cursor); if (!block.next().isValid() && line.isValid() && line.lineNumber() == block.layout()->lineCount() - 1) op = QTextCursor::End; } } } break; case Qt::Key_Left: if (twoModifiers) { QApplication::beep(); return true; } else { if (e->modifiers() & (Qt::ControlModifier | Qt::MetaModifier)) op = QTextCursor::StartOfLine; else if (e->modifiers() & Qt::AltModifier) op = QTextCursor::WordLeft; else op = QTextCursor::Left; } break; case Qt::Key_Right: if (twoModifiers) { QApplication::beep(); return true; } else { if (e->modifiers() & (Qt::ControlModifier | Qt::MetaModifier)) op = QTextCursor::EndOfLine; else if (e->modifiers() & Qt::AltModifier) op = QTextCursor::WordRight; else op = QTextCursor::Right; } break; case Qt::Key_Home: if (e->modifiers() & (Qt::ControlModifier | Qt::MetaModifier | Qt::AltModifier)) { QApplication::beep(); return true; } else { op = QTextCursor::Start; } break; case Qt::Key_End: if (e->modifiers() & (Qt::ControlModifier | Qt::MetaModifier | Qt::AltModifier)) { QApplication::beep(); return true; } else { op = QTextCursor::End; } break;#endif case Qt::Key_PageDown: pageDown(mode); break; case Qt::Key_PageUp: pageUp(mode); break; default: return false; } const bool moved = cursor.movePosition(op, mode); q->ensureCursorVisible(); if (moved) { emit q->cursorPositionChanged(); q->updateMicroFocus(); }#ifdef QT_KEYPAD_NAVIGATION else if (QApplication::keypadNavigationEnabled() && (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down)) { return false; }#endif selectionChanged(); repaintSelection(); return true;}void QTextEditPrivate::updateCurrentCharFormat(){ Q_Q(QTextEdit); QTextCharFormat fmt = cursor.charFormat(); if (fmt == lastCharFormat) return; lastCharFormat = fmt; emit q->currentCharFormatChanged(fmt);#ifdef QT3_SUPPORT // compat signals emit q->currentFontChanged(fmt.font()); emit q->currentColorChanged(fmt.foreground().color());#endif q->updateMicroFocus();}void QTextEditPrivate::indent(){ QTextBlockFormat blockFmt = cursor.blockFormat(); QTextList *list = cursor.currentList(); if (!list) { QTextBlockFormat modifier; modifier.setIndent(blockFmt.indent() + 1); cursor.mergeBlockFormat(modifier); } else { QTextListFormat format = list->format(); format.setIndent(format.indent() + 1); if (list->itemNumber(cursor.block()) == 1) list->setFormat(format); else cursor.createList(format); }}void QTextEditPrivate::outdent(){ QTextBlockFormat blockFmt = cursor.blockFormat(); QTextList *list = cursor.currentList(); if (!list) { QTextBlockFormat modifier; modifier.setIndent(blockFmt.indent() - 1); cursor.mergeBlockFormat(modifier); } else { QTextListFormat listFmt = list->format(); listFmt.setIndent(listFmt.indent() - 1); list->setFormat(listFmt); }}void QTextEditPrivate::gotoNextTableCell(){ QTextTable *table = cursor.currentTable(); QTextTableCell cell = table->cellAt(cursor); int newColumn = cell.column() + cell.columnSpan(); int newRow = cell.row(); if (newColumn >= table->columns()) { newColumn = 0; ++newRow; if (newRow >= table->rows()) table->insertRows(table->rows(), 1); } cell = table->cellAt(newRow, newColumn); cursor = cell.firstCursorPosition();}void QTextEditPrivate::gotoPreviousTableCell(){ QTextTable *table = cursor.currentTable(); QTextTableCell cell = table->cellAt(cursor); int newColumn = cell.column() - 1; int newRow = cell.row(); if (newColumn < 0) { newColumn = table->columns() - 1; --newRow; if (newRow < 0) return; } cell = table->cellAt(newRow, newColumn); cursor = cell.firstCursorPosition();}void QTextEditPrivate::createAutoBulletList(){ cursor.beginEditBlock(); QTextBlockFormat blockFmt = cursor.blockFormat(); QTextListFormat listFmt; listFmt.setStyle(QTextListFormat::ListDisc); listFmt.setIndent(blockFmt.indent() + 1); blockFmt.setIndent(0); cursor.setBlockFormat(blockFmt); cursor.createList(listFmt); cursor.endEditBlock();}void QTextEditPrivate::init(const QString &html){ Q_Q(QTextEdit); setContent(Qt::RichText, html); hbar->setSingleStep(20); vbar->setSingleStep(20); viewport->setBackgroundRole(QPalette::Base); q->setAcceptDrops(true); q->setFocusPolicy(Qt::WheelFocus); q->setAttribute(Qt::WA_KeyCompression);#ifndef QT_NO_CURSOR viewport->setCursor(Qt::IBeamCursor);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -