diff options
Diffstat (limited to 'src/gui/text/qtextcontrol.cpp')
-rw-r--r-- | src/gui/text/qtextcontrol.cpp | 3148 |
1 files changed, 0 insertions, 3148 deletions
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp deleted file mode 100644 index 347761a1ee..0000000000 --- a/src/gui/text/qtextcontrol.cpp +++ /dev/null @@ -1,3148 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.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 the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtextcontrol_p.h" -#include "qtextcontrol_p_p.h" - -#ifndef QT_NO_TEXTCONTROL - -#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 "private/qabstracttextdocumentlayout_p.h" -#include "private/qtextedit_p.h" -#include "qtextdocument.h" -#include "private/qtextdocument_p.h" -#include "qtextlist.h" -#include "private/qtextcontrol_p.h" -#include "qgraphicssceneevent.h" -#include "qprinter.h" -#include "qtextdocumentwriter.h" -#include "private/qtextcursor_p.h" - -#include <qtextformat.h> -#include <qdatetime.h> -#include <qbuffer.h> -#include <qapplication.h> -#include <limits.h> -#include <qtexttable.h> -#include <qvariant.h> -#include <qurl.h> -#include <qdesktopservices.h> -#include <qinputcontext.h> -#include <qtooltip.h> -#include <qstyleoption.h> -#include <QtGui/qlineedit.h> - -#ifndef QT_NO_SHORTCUT -#include "private/qapplication_p.h" -#include "private/qshortcutmap_p.h" -#include <qkeysequence.h> -#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1Char('\t') + QString(QKeySequence(k)) : QString()) -#else -#define ACCEL_KEY(k) QString() -#endif - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_CONTEXTMENU -#if defined(Q_WS_WIN) || defined(Q_WS_X11) -extern bool qt_use_rtl_extensions; -#endif -#endif - -// 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); -} - -QTextControlPrivate::QTextControlPrivate() - : doc(0), cursorOn(false), cursorIsFocusIndicator(false), - interactionFlags(Qt::TextEditorInteraction), - dragEnabled(true), -#ifndef QT_NO_DRAGANDDROP - mousePressed(false), mightStartDrag(false), -#endif - lastSelectionState(false), ignoreAutomaticScrollbarAdjustement(false), - overwriteMode(false), - acceptRichText(true), - preeditCursor(0), hideCursor(false), - hasFocus(false), -#ifdef QT_KEYPAD_NAVIGATION - hasEditFocus(false), -#endif - isEnabled(true), - hadSelectionOnMousePress(false), - ignoreUnusedNavigationEvents(false), - openExternalLinks(false), - wordSelectionEnabled(false) -{} - -bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) -{ -#ifdef QT_NO_SHORTCUT - Q_UNUSED(e); -#endif - - Q_Q(QTextControl); - if (cursor.isNull()) - return false; - - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - - QTextCursor::MoveMode mode = QTextCursor::MoveAnchor; - QTextCursor::MoveOperation op = QTextCursor::NoMove; - - if (false) { - } -#ifndef QT_NO_SHORTCUT - if (e == QKeySequence::MoveToNextChar) { - op = QTextCursor::Right; - } - else if (e == QKeySequence::MoveToPreviousChar) { - op = QTextCursor::Left; - } - else if (e == QKeySequence::SelectNextChar) { - op = QTextCursor::Right; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectPreviousChar) { - op = QTextCursor::Left; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectNextWord) { - op = QTextCursor::WordRight; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectPreviousWord) { - op = QTextCursor::WordLeft; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectStartOfLine) { - op = QTextCursor::StartOfLine; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectEndOfLine) { - op = QTextCursor::EndOfLine; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectStartOfBlock) { - op = QTextCursor::StartOfBlock; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectEndOfBlock) { - op = QTextCursor::EndOfBlock; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectStartOfDocument) { - op = QTextCursor::Start; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectEndOfDocument) { - op = QTextCursor::End; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectPreviousLine) { - op = QTextCursor::Up; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectNextLine) { - op = QTextCursor::Down; - 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; - } - } - else if (e == QKeySequence::MoveToNextWord) { - op = QTextCursor::WordRight; - } - else if (e == QKeySequence::MoveToPreviousWord) { - op = QTextCursor::WordLeft; - } - else if (e == QKeySequence::MoveToEndOfBlock) { - op = QTextCursor::EndOfBlock; - } - else if (e == QKeySequence::MoveToStartOfBlock) { - op = QTextCursor::StartOfBlock; - } - else if (e == QKeySequence::MoveToNextLine) { - op = QTextCursor::Down; - } - else if (e == QKeySequence::MoveToPreviousLine) { - op = QTextCursor::Up; - } - else if (e == QKeySequence::MoveToPreviousLine) { - op = QTextCursor::Up; - } - else if (e == QKeySequence::MoveToStartOfLine) { - op = QTextCursor::StartOfLine; - } - else if (e == QKeySequence::MoveToEndOfLine) { - op = QTextCursor::EndOfLine; - } - else if (e == QKeySequence::MoveToStartOfDocument) { - op = QTextCursor::Start; - } - else if (e == QKeySequence::MoveToEndOfDocument) { - op = QTextCursor::End; - } -#endif // QT_NO_SHORTCUT - else { - return false; - } - -// 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) - - bool visualNavigation = cursor.visualNavigation(); - cursor.setVisualNavigation(true); - const bool moved = cursor.movePosition(op, mode); - cursor.setVisualNavigation(visualNavigation); - q->ensureCursorVisible(); - - bool ignoreNavigationEvents = ignoreUnusedNavigationEvents; - bool isNavigationEvent = e->key() == Qt::Key_Up || e->key() == Qt::Key_Down; - -#ifdef QT_KEYPAD_NAVIGATION - ignoreNavigationEvents = ignoreNavigationEvents || QApplication::keypadNavigationEnabled(); - isNavigationEvent = isNavigationEvent || - (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional - && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)); -#else - isNavigationEvent = isNavigationEvent || e->key() == Qt::Key_Left || e->key() == Qt::Key_Right; -#endif - - if (moved) { - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - emit q->microFocusChanged(); - } else if (ignoreNavigationEvents && isNavigationEvent && oldSelection.anchor() == cursor.anchor()) { - return false; - } - - selectionChanged(/*forceEmitSelectionChanged =*/(mode == QTextCursor::KeepAnchor)); - - repaintOldAndNewSelection(oldSelection); - - return true; -} - -void QTextControlPrivate::updateCurrentCharFormat() -{ - Q_Q(QTextControl); - - QTextCharFormat fmt = cursor.charFormat(); - if (fmt == lastCharFormat) - return; - lastCharFormat = fmt; - - emit q->currentCharFormatChanged(fmt); - emit q->microFocusChanged(); -} - -void QTextControlPrivate::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 QTextControlPrivate::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 QTextControlPrivate::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 QTextControlPrivate::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 QTextControlPrivate::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 QTextControlPrivate::init(Qt::TextFormat format, const QString &text, QTextDocument *document) -{ - Q_Q(QTextControl); - setContent(format, text, document); - - doc->setUndoRedoEnabled(interactionFlags & Qt::TextEditable); - q->setCursorWidth(-1); -} - -void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text, QTextDocument *document) -{ - Q_Q(QTextControl); - - // for use when called from setPlainText. we may want to re-use the currently - // set char format then. - const QTextCharFormat charFormatForInsertion = cursor.charFormat(); - - bool clearDocument = true; - if (!doc) { - if (document) { - doc = document; - clearDocument = false; - } else { - palette = QApplication::palette("QTextControl"); - doc = new QTextDocument(q); - } - _q_documentLayoutChanged(); - cursor = QTextCursor(doc); - -// #### doc->documentLayout()->setPaintDevice(viewport); - - QObject::connect(doc, SIGNAL(contentsChanged()), q, SLOT(_q_updateCurrentCharFormatAndSelection())); - QObject::connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)), q, SLOT(_q_emitCursorPosChanged(QTextCursor))); - QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged())); - - // convenience signal forwards - QObject::connect(doc, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool))); - QObject::connect(doc, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool))); - QObject::connect(doc, SIGNAL(modificationChanged(bool)), q, SIGNAL(modificationChanged(bool))); - QObject::connect(doc, SIGNAL(blockCountChanged(int)), q, SIGNAL(blockCountChanged(int))); - } - - bool previousUndoRedoState = doc->isUndoRedoEnabled(); - if (!document) - doc->setUndoRedoEnabled(false); - - //Saving the index save some time. - static int contentsChangedIndex = QTextDocument::staticMetaObject.indexOfSignal("contentsChanged()"); - static int textChangedIndex = QTextControl::staticMetaObject.indexOfSignal("textChanged()"); - // avoid multiple textChanged() signals being emitted - QMetaObject::disconnect(doc, contentsChangedIndex, q, textChangedIndex); - - if (!text.isEmpty()) { - // clear 'our' cursor for insertion to prevent - // the emission of the cursorPositionChanged() signal. - // instead we emit it only once at the end instead of - // at the end of the document after loading and when - // positioning the cursor again to the start of the - // document. - cursor = QTextCursor(); - if (format == Qt::PlainText) { - QTextCursor formatCursor(doc); - // put the setPlainText and the setCharFormat into one edit block, - // so that the syntax highlight triggers only /once/ for the entire - // document, not twice. - formatCursor.beginEditBlock(); - doc->setPlainText(text); - doc->setUndoRedoEnabled(false); - formatCursor.select(QTextCursor::Document); - formatCursor.setCharFormat(charFormatForInsertion); - formatCursor.endEditBlock(); - } else { -#ifndef QT_NO_TEXTHTMLPARSER - doc->setHtml(text); -#else - doc->setPlainText(text); -#endif - doc->setUndoRedoEnabled(false); - } - cursor = QTextCursor(doc); - } else if (clearDocument) { - doc->clear(); - } - cursor.setCharFormat(charFormatForInsertion); - - QMetaObject::connect(doc, contentsChangedIndex, q, textChangedIndex); - emit q->textChanged(); - if (!document) - doc->setUndoRedoEnabled(previousUndoRedoState); - _q_updateCurrentCharFormatAndSelection(); - if (!document) - doc->setModified(false); - - q->ensureCursorVisible(); - emit q->cursorPositionChanged(); -} - -void QTextControlPrivate::startDrag() -{ -#ifndef QT_NO_DRAGANDDROP - Q_Q(QTextControl); - mousePressed = false; - if (!contextWidget) - return; - QMimeData *data = q->createMimeDataFromSelection(); - - QDrag *drag = new QDrag(contextWidget); - drag->setMimeData(data); - - Qt::DropActions actions = Qt::CopyAction; - Qt::DropAction action; - if (interactionFlags & Qt::TextEditable) { - actions |= Qt::MoveAction; - action = drag->exec(actions, Qt::MoveAction); - } else { - action = drag->exec(actions, Qt::CopyAction); - } - - if (action == Qt::MoveAction && drag->target() != contextWidget) - cursor.removeSelectedText(); -#endif -} - -void QTextControlPrivate::setCursorPosition(const QPointF &pos) -{ - Q_Q(QTextControl); - const int cursorPos = q->hitTest(pos, Qt::FuzzyHit); - if (cursorPos == -1) - return; - cursor.setPosition(cursorPos); -} - -void QTextControlPrivate::setCursorPosition(int pos, QTextCursor::MoveMode mode) -{ - cursor.setPosition(pos, mode); - - if (mode != QTextCursor::KeepAnchor) { - selectedWordOnDoubleClick = QTextCursor(); - selectedBlockOnTrippleClick = QTextCursor(); - } -} - -void QTextControlPrivate::repaintCursor() -{ - Q_Q(QTextControl); - emit q->updateRequest(cursorRectPlusUnicodeDirectionMarkers(cursor)); -} - -void QTextControlPrivate::repaintOldAndNewSelection(const QTextCursor &oldSelection) -{ - Q_Q(QTextControl); - if (cursor.hasSelection() - && oldSelection.hasSelection() - && cursor.currentFrame() == oldSelection.currentFrame() - && !cursor.hasComplexSelection() - && !oldSelection.hasComplexSelection() - && cursor.anchor() == oldSelection.anchor() - ) { - QTextCursor differenceSelection(doc); - differenceSelection.setPosition(oldSelection.position()); - differenceSelection.setPosition(cursor.position(), QTextCursor::KeepAnchor); - emit q->updateRequest(q->selectionRect(differenceSelection)); - } else { - if (!oldSelection.isNull()) - emit q->updateRequest(q->selectionRect(oldSelection) | cursorRectPlusUnicodeDirectionMarkers(oldSelection)); - emit q->updateRequest(q->selectionRect() | cursorRectPlusUnicodeDirectionMarkers(cursor)); - } -} - -void QTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged /*=false*/) -{ - Q_Q(QTextControl); - if (forceEmitSelectionChanged) - emit q->selectionChanged(); - - bool current = cursor.hasSelection(); - if (current == lastSelectionState) - return; - - lastSelectionState = current; - emit q->copyAvailable(current); - if (!forceEmitSelectionChanged) - emit q->selectionChanged(); - emit q->microFocusChanged(); -} - -void QTextControlPrivate::_q_updateCurrentCharFormatAndSelection() -{ - updateCurrentCharFormat(); - selectionChanged(); -} - -#ifndef QT_NO_CLIPBOARD -void QTextControlPrivate::setClipboardSelection() -{ - QClipboard *clipboard = QApplication::clipboard(); - if (!cursor.hasSelection() || !clipboard->supportsSelection()) - return; - Q_Q(QTextControl); - QMimeData *data = q->createMimeDataFromSelection(); - clipboard->setMimeData(data, QClipboard::Selection); -} -#endif - -void QTextControlPrivate::_q_emitCursorPosChanged(const QTextCursor &someCursor) -{ - Q_Q(QTextControl); - if (someCursor.isCopyOf(cursor)) { - emit q->cursorPositionChanged(); - emit q->microFocusChanged(); - } -} - -void QTextControlPrivate::_q_documentLayoutChanged() -{ - Q_Q(QTextControl); - QAbstractTextDocumentLayout *layout = doc->documentLayout(); - QObject::connect(layout, SIGNAL(update(QRectF)), q, SIGNAL(updateRequest(QRectF))); - QObject::connect(layout, SIGNAL(updateBlock(QTextBlock)), q, SLOT(_q_updateBlock(QTextBlock))); - QObject::connect(layout, SIGNAL(documentSizeChanged(QSizeF)), q, SIGNAL(documentSizeChanged(QSizeF))); - -} - -void QTextControlPrivate::setBlinkingCursorEnabled(bool enable) -{ - Q_Q(QTextControl); - - if (enable && QApplication::cursorFlashTime() > 0) - cursorBlinkTimer.start(QApplication::cursorFlashTime() / 2, q); - else - cursorBlinkTimer.stop(); - - cursorOn = enable; - - repaintCursor(); -} - -void QTextControlPrivate::extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition) -{ - Q_Q(QTextControl); - - // if inside the initial selected word keep that - if (suggestedNewPosition >= selectedWordOnDoubleClick.selectionStart() - && suggestedNewPosition <= selectedWordOnDoubleClick.selectionEnd()) { - q->setTextCursor(selectedWordOnDoubleClick); - return; - } - - QTextCursor curs = selectedWordOnDoubleClick; - curs.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor); - - if (!curs.movePosition(QTextCursor::StartOfWord)) - return; - const int wordStartPos = curs.position(); - - const int blockPos = curs.block().position(); - const QPointF blockCoordinates = q->blockBoundingRect(curs.block()).topLeft(); - - QTextLine line = currentTextLine(curs); - if (!line.isValid()) - return; - - const qreal wordStartX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x(); - - if (!curs.movePosition(QTextCursor::EndOfWord)) - return; - const int wordEndPos = curs.position(); - - const QTextLine otherLine = currentTextLine(curs); - if (otherLine.textStart() != line.textStart() - || wordEndPos == wordStartPos) - return; - - const qreal wordEndX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x(); - - if (mouseXPosition < wordStartX || mouseXPosition > wordEndX) - return; - - // keep the already selected word even when moving to the left - // (#39164) - if (suggestedNewPosition < selectedWordOnDoubleClick.position()) - cursor.setPosition(selectedWordOnDoubleClick.selectionEnd()); - else - cursor.setPosition(selectedWordOnDoubleClick.selectionStart()); - - const qreal differenceToStart = mouseXPosition - wordStartX; - const qreal differenceToEnd = wordEndX - mouseXPosition; - - if (differenceToStart < differenceToEnd) - setCursorPosition(wordStartPos, QTextCursor::KeepAnchor); - else - setCursorPosition(wordEndPos, QTextCursor::KeepAnchor); - - if (interactionFlags & Qt::TextSelectableByMouse) { -#ifndef QT_NO_CLIPBOARD - setClipboardSelection(); -#endif - selectionChanged(true); - } -} - -void QTextControlPrivate::extendBlockwiseSelection(int suggestedNewPosition) -{ - Q_Q(QTextControl); - - // if inside the initial selected line keep that - if (suggestedNewPosition >= selectedBlockOnTrippleClick.selectionStart() - && suggestedNewPosition <= selectedBlockOnTrippleClick.selectionEnd()) { - q->setTextCursor(selectedBlockOnTrippleClick); - return; - } - - if (suggestedNewPosition < selectedBlockOnTrippleClick.position()) { - cursor.setPosition(selectedBlockOnTrippleClick.selectionEnd()); - cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor); - cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); - } else { - cursor.setPosition(selectedBlockOnTrippleClick.selectionStart()); - cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor); - cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); - } - - if (interactionFlags & Qt::TextSelectableByMouse) { -#ifndef QT_NO_CLIPBOARD - setClipboardSelection(); -#endif - selectionChanged(true); - } -} - -void QTextControlPrivate::_q_deleteSelected() -{ - if (!(interactionFlags & Qt::TextEditable) || !cursor.hasSelection()) - return; - cursor.removeSelectedText(); -} - -void QTextControl::undo() -{ - Q_D(QTextControl); - d->repaintSelection(); - const int oldCursorPos = d->cursor.position(); - d->doc->undo(&d->cursor); - if (d->cursor.position() != oldCursorPos) - emit cursorPositionChanged(); - emit microFocusChanged(); - ensureCursorVisible(); -} - -void QTextControl::redo() -{ - Q_D(QTextControl); - d->repaintSelection(); - const int oldCursorPos = d->cursor.position(); - d->doc->redo(&d->cursor); - if (d->cursor.position() != oldCursorPos) - emit cursorPositionChanged(); - emit microFocusChanged(); - ensureCursorVisible(); -} - -QTextControl::QTextControl(QObject *parent) - : QObject(*new QTextControlPrivate, parent) -{ - Q_D(QTextControl); - d->init(); -} - -QTextControl::QTextControl(const QString &text, QObject *parent) - : QObject(*new QTextControlPrivate, parent) -{ - Q_D(QTextControl); - d->init(Qt::RichText, text); -} - -QTextControl::QTextControl(QTextDocument *doc, QObject *parent) - : QObject(*new QTextControlPrivate, parent) -{ - Q_D(QTextControl); - d->init(Qt::RichText, QString(), doc); -} - -QTextControl::~QTextControl() -{ -} - -void QTextControl::setDocument(QTextDocument *document) -{ - Q_D(QTextControl); - if (d->doc == document) - return; - - d->doc->disconnect(this); - d->doc->documentLayout()->disconnect(this); - d->doc->documentLayout()->setPaintDevice(0); - - if (d->doc->parent() == this) - delete d->doc; - - d->doc = 0; - d->setContent(Qt::RichText, QString(), document); -} - -QTextDocument *QTextControl::document() const -{ - Q_D(const QTextControl); - return d->doc; -} - -void QTextControl::setTextCursor(const QTextCursor &cursor) -{ - Q_D(QTextControl); - d->cursorIsFocusIndicator = false; - const bool posChanged = cursor.position() != d->cursor.position(); - const QTextCursor oldSelection = d->cursor; - d->cursor = cursor; - d->cursorOn = d->hasFocus && (d->interactionFlags & Qt::TextEditable); - d->_q_updateCurrentCharFormatAndSelection(); - ensureCursorVisible(); - d->repaintOldAndNewSelection(oldSelection); - if (posChanged) - emit cursorPositionChanged(); -} - -QTextCursor QTextControl::textCursor() const -{ - Q_D(const QTextControl); - return d->cursor; -} - -#ifndef QT_NO_CLIPBOARD - -void QTextControl::cut() -{ - Q_D(QTextControl); - if (!(d->interactionFlags & Qt::TextEditable) || !d->cursor.hasSelection()) - return; - copy(); - d->cursor.removeSelectedText(); -} - -void QTextControl::copy() -{ - Q_D(QTextControl); - if (!d->cursor.hasSelection()) - return; - QMimeData *data = createMimeDataFromSelection(); - QApplication::clipboard()->setMimeData(data); -} - -void QTextControl::paste(QClipboard::Mode mode) -{ - const QMimeData *md = QApplication::clipboard()->mimeData(mode); - if (md) - insertFromMimeData(md); -} -#endif - -void QTextControl::clear() -{ - Q_D(QTextControl); - // clears and sets empty content - d->extraSelections.clear(); - d->setContent(); -} - - -void QTextControl::selectAll() -{ - Q_D(QTextControl); - const int selectionLength = qAbs(d->cursor.position() - d->cursor.anchor()); - d->cursor.select(QTextCursor::Document); - d->selectionChanged(selectionLength != qAbs(d->cursor.position() - d->cursor.anchor())); - d->cursorIsFocusIndicator = false; - emit updateRequest(); -} - -void QTextControl::processEvent(QEvent *e, const QPointF &coordinateOffset, QWidget *contextWidget) -{ - QMatrix m; - m.translate(coordinateOffset.x(), coordinateOffset.y()); - processEvent(e, m, contextWidget); -} - -void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *contextWidget) -{ - Q_D(QTextControl); - if (d->interactionFlags == Qt::NoTextInteraction) { - e->ignore(); - return; - } - - d->contextWidget = contextWidget; - - if (!d->contextWidget) { - switch (e->type()) { -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMouseMove: - case QEvent::GraphicsSceneMousePress: - case QEvent::GraphicsSceneMouseRelease: - case QEvent::GraphicsSceneMouseDoubleClick: - case QEvent::GraphicsSceneContextMenu: - case QEvent::GraphicsSceneHoverEnter: - case QEvent::GraphicsSceneHoverMove: - case QEvent::GraphicsSceneHoverLeave: - case QEvent::GraphicsSceneHelp: - case QEvent::GraphicsSceneDragEnter: - case QEvent::GraphicsSceneDragMove: - case QEvent::GraphicsSceneDragLeave: - case QEvent::GraphicsSceneDrop: { - QGraphicsSceneEvent *ev = static_cast<QGraphicsSceneEvent *>(e); - d->contextWidget = ev->widget(); - break; - } -#endif // QT_NO_GRAPHICSVIEW - default: break; - }; - } - - switch (e->type()) { - case QEvent::KeyPress: - d->keyPressEvent(static_cast<QKeyEvent *>(e)); - break; - case QEvent::MouseButtonPress: { - QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), - ev->buttons(), ev->globalPos()); - break; } - case QEvent::MouseMove: { - QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), - ev->buttons(), ev->globalPos()); - break; } - case QEvent::MouseButtonRelease: { - QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), - ev->buttons(), ev->globalPos()); - break; } - case QEvent::MouseButtonDblClick: { - QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), - ev->buttons(), ev->globalPos()); - break; } - case QEvent::InputMethod: - d->inputMethodEvent(static_cast<QInputMethodEvent *>(e)); - break; -#ifndef QT_NO_CONTEXTMENU - case QEvent::ContextMenu: { - QContextMenuEvent *ev = static_cast<QContextMenuEvent *>(e); - d->contextMenuEvent(ev->globalPos(), matrix.map(ev->pos()), contextWidget); - break; } -#endif // QT_NO_CONTEXTMENU - case QEvent::FocusIn: - case QEvent::FocusOut: - d->focusEvent(static_cast<QFocusEvent *>(e)); - break; - - case QEvent::EnabledChange: - d->isEnabled = e->isAccepted(); - break; - -#ifndef QT_NO_TOOLTIP - case QEvent::ToolTip: { - QHelpEvent *ev = static_cast<QHelpEvent *>(e); - d->showToolTip(ev->globalPos(), matrix.map(ev->pos()), contextWidget); - break; - } -#endif // QT_NO_TOOLTIP - -#ifndef QT_NO_DRAGANDDROP - case QEvent::DragEnter: { - QDragEnterEvent *ev = static_cast<QDragEnterEvent *>(e); - if (d->dragEnterEvent(e, ev->mimeData())) - ev->acceptProposedAction(); - break; - } - case QEvent::DragLeave: - d->dragLeaveEvent(); - break; - case QEvent::DragMove: { - QDragMoveEvent *ev = static_cast<QDragMoveEvent *>(e); - if (d->dragMoveEvent(e, ev->mimeData(), matrix.map(ev->pos()))) - ev->acceptProposedAction(); - break; - } - case QEvent::Drop: { - QDropEvent *ev = static_cast<QDropEvent *>(e); - if (d->dropEvent(ev->mimeData(), matrix.map(ev->pos()), ev->dropAction(), ev->source())) - ev->acceptProposedAction(); - break; - } -#endif - -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMousePress: { - QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), - ev->screenPos()); - break; } - case QEvent::GraphicsSceneMouseMove: { - QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), - ev->screenPos()); - break; } - case QEvent::GraphicsSceneMouseRelease: { - QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), - ev->screenPos()); - break; } - case QEvent::GraphicsSceneMouseDoubleClick: { - QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), - ev->screenPos()); - break; } - case QEvent::GraphicsSceneContextMenu: { - QGraphicsSceneContextMenuEvent *ev = static_cast<QGraphicsSceneContextMenuEvent *>(e); - d->contextMenuEvent(ev->screenPos(), matrix.map(ev->pos()), contextWidget); - break; } - - case QEvent::GraphicsSceneHoverMove: { - QGraphicsSceneHoverEvent *ev = static_cast<QGraphicsSceneHoverEvent *>(e); - d->mouseMoveEvent(ev, Qt::NoButton, matrix.map(ev->pos()), ev->modifiers(),Qt::NoButton, - ev->screenPos()); - break; } - - case QEvent::GraphicsSceneDragEnter: { - QGraphicsSceneDragDropEvent *ev = static_cast<QGraphicsSceneDragDropEvent *>(e); - if (d->dragEnterEvent(e, ev->mimeData())) - ev->acceptProposedAction(); - break; } - case QEvent::GraphicsSceneDragLeave: - d->dragLeaveEvent(); - break; - case QEvent::GraphicsSceneDragMove: { - QGraphicsSceneDragDropEvent *ev = static_cast<QGraphicsSceneDragDropEvent *>(e); - if (d->dragMoveEvent(e, ev->mimeData(), matrix.map(ev->pos()))) - ev->acceptProposedAction(); - break; } - case QEvent::GraphicsSceneDrop: { - QGraphicsSceneDragDropEvent *ev = static_cast<QGraphicsSceneDragDropEvent *>(e); - if (d->dropEvent(ev->mimeData(), matrix.map(ev->pos()), ev->dropAction(), ev->source())) - ev->accept(); - break; } -#endif // QT_NO_GRAPHICSVIEW -#ifdef QT_KEYPAD_NAVIGATION - case QEvent::EnterEditFocus: - case QEvent::LeaveEditFocus: - if (QApplication::keypadNavigationEnabled()) - d->editFocusEvent(e); - break; -#endif - case QEvent::ShortcutOverride: - if (d->interactionFlags & Qt::TextEditable) { - QKeyEvent* ke = static_cast<QKeyEvent *>(e); - if (ke->modifiers() == Qt::NoModifier - || ke->modifiers() == Qt::ShiftModifier - || ke->modifiers() == Qt::KeypadModifier) { - if (ke->key() < Qt::Key_Escape) { - ke->accept(); - } else { - switch (ke->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Backspace: - case Qt::Key_Left: - case Qt::Key_Right: - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Tab: - ke->accept(); - default: - break; - } - } -#ifndef QT_NO_SHORTCUT - } else if (ke == QKeySequence::Copy - || ke == QKeySequence::Paste - || ke == QKeySequence::Cut - || ke == QKeySequence::Redo - || ke == QKeySequence::Undo - || ke == QKeySequence::MoveToNextWord - || ke == QKeySequence::MoveToPreviousWord - || ke == QKeySequence::MoveToStartOfDocument - || ke == QKeySequence::MoveToEndOfDocument - || ke == QKeySequence::SelectNextWord - || ke == QKeySequence::SelectPreviousWord - || ke == QKeySequence::SelectStartOfLine - || ke == QKeySequence::SelectEndOfLine - || ke == QKeySequence::SelectStartOfBlock - || ke == QKeySequence::SelectEndOfBlock - || ke == QKeySequence::SelectStartOfDocument - || ke == QKeySequence::SelectEndOfDocument - || ke == QKeySequence::SelectAll - ) { - ke->accept(); -#endif - } - } - break; - default: - break; - } -} - -bool QTextControl::event(QEvent *e) -{ - return QObject::event(e); -} - -void QTextControl::timerEvent(QTimerEvent *e) -{ - Q_D(QTextControl); - if (e->timerId() == d->cursorBlinkTimer.timerId()) { - d->cursorOn = !d->cursorOn; - - if (d->cursor.hasSelection()) - d->cursorOn &= (QApplication::style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected) - != 0); - - d->repaintCursor(); - } else if (e->timerId() == d->trippleClickTimer.timerId()) { - d->trippleClickTimer.stop(); - } -} - -void QTextControl::setPlainText(const QString &text) -{ - Q_D(QTextControl); - d->setContent(Qt::PlainText, text); -} - -void QTextControl::setHtml(const QString &text) -{ - Q_D(QTextControl); - d->setContent(Qt::RichText, text); -} - -void QTextControlPrivate::keyPressEvent(QKeyEvent *e) -{ - Q_Q(QTextControl); -#ifndef QT_NO_SHORTCUT - if (e == QKeySequence::SelectAll) { - e->accept(); - q->selectAll(); - return; - } -#ifndef QT_NO_CLIPBOARD - else if (e == QKeySequence::Copy) { - e->accept(); - q->copy(); - return; - } -#endif -#endif // QT_NO_SHORTCUT - - if (interactionFlags & Qt::TextSelectableByKeyboard - && cursorMoveKeyEvent(e)) - goto accept; - - if (interactionFlags & Qt::LinksAccessibleByKeyboard) { - if ((e->key() == Qt::Key_Return - || e->key() == Qt::Key_Enter -#ifdef QT_KEYPAD_NAVIGATION - || e->key() == Qt::Key_Select -#endif - ) - && cursor.hasSelection()) { - - e->accept(); - activateLinkUnderCursor(); - return; - } - } - - if (!(interactionFlags & Qt::TextEditable)) { - e->ignore(); - return; - } - - if (e->key() == Qt::Key_Direction_L || e->key() == Qt::Key_Direction_R) { - QTextBlockFormat fmt; - fmt.setLayoutDirection((e->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft); - cursor.mergeBlockFormat(fmt); - goto accept; - } - - // schedule a repaint of the region of the cursor, as when we move it we - // want to make sure the old cursor disappears (not noticeable when moving - // only a few pixels but noticeable when jumping between cells in tables for - // example) - repaintSelection(); - - if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~Qt::ShiftModifier)) { - QTextBlockFormat blockFmt = cursor.blockFormat(); - QTextList *list = cursor.currentList(); - if (list && cursor.atBlockStart() && !cursor.hasSelection()) { - list->remove(cursor.block()); - } else if (cursor.atBlockStart() && blockFmt.indent() > 0) { - blockFmt.setIndent(blockFmt.indent() - 1); - cursor.setBlockFormat(blockFmt); - } else { - QTextCursor localCursor = cursor; - localCursor.deletePreviousChar(); - } - goto accept; - } -#ifndef QT_NO_SHORTCUT - else if (e == QKeySequence::InsertParagraphSeparator) { - cursor.insertBlock(); - e->accept(); - goto accept; - } else if (e == QKeySequence::InsertLineSeparator) { - cursor.insertText(QString(QChar::LineSeparator)); - e->accept(); - goto accept; - } -#endif - if (false) { - } -#ifndef QT_NO_SHORTCUT - else if (e == QKeySequence::Undo) { - q->undo(); - } - else if (e == QKeySequence::Redo) { - q->redo(); - } -#ifndef QT_NO_CLIPBOARD - else if (e == QKeySequence::Cut) { - q->cut(); - } - else if (e == QKeySequence::Paste) { - QClipboard::Mode mode = QClipboard::Clipboard; -#ifdef Q_WS_X11 - if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert) - mode = QClipboard::Selection; -#endif - q->paste(mode); - } -#endif - else if (e == QKeySequence::Delete) { - QTextCursor localCursor = cursor; - localCursor.deleteChar(); - } - else if (e == QKeySequence::DeleteEndOfWord) { - if (!cursor.hasSelection()) - cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - } - else if (e == QKeySequence::DeleteStartOfWord) { - if (!cursor.hasSelection()) - cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - } - else if (e == QKeySequence::DeleteEndOfLine) { - QTextBlock block = cursor.block(); - if (cursor.position() == block.position() + block.length() - 2) - cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); - else - cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - } -#endif // QT_NO_SHORTCUT - else { - goto process; - } - goto accept; - -process: - { - QString text = e->text(); - if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t'))) { - if (overwriteMode - // no need to call deleteChar() if we have a selection, insertText - // does it already - && !cursor.hasSelection() - && !cursor.atBlockEnd()) - cursor.deleteChar(); - - cursor.insertText(text); - selectionChanged(); - } else { - e->ignore(); - return; - } - } - - accept: - - e->accept(); - cursorOn = true; - - q->ensureCursorVisible(); - - updateCurrentCharFormat(); -} - -QVariant QTextControl::loadResource(int type, const QUrl &name) -{ -#ifdef QT_NO_TEXTEDIT - Q_UNUSED(type); - Q_UNUSED(name); -#else - if (QTextEdit *textEdit = qobject_cast<QTextEdit *>(parent())) { - QUrl resolvedName = textEdit->d_func()->resolveUrl(name); - return textEdit->loadResource(type, resolvedName); - } -#endif - return QVariant(); -} - -void QTextControlPrivate::_q_updateBlock(const QTextBlock &block) -{ - Q_Q(QTextControl); - QRectF br = q->blockBoundingRect(block); - br.setRight(qreal(INT_MAX)); // the block might have shrunk - emit q->updateRequest(br); -} - -QRectF QTextControlPrivate::rectForPosition(int position) const -{ - Q_Q(const QTextControl); - const QTextBlock block = doc->findBlock(position); - if (!block.isValid()) - return QRectF(); - const QAbstractTextDocumentLayout *docLayout = doc->documentLayout(); - const QTextLayout *layout = block.layout(); - const QPointF layoutPos = q->blockBoundingRect(block).topLeft(); - int relativePos = position - block.position(); - if (preeditCursor != 0) { - int preeditPos = layout->preeditAreaPosition(); - if (relativePos == preeditPos) - relativePos += preeditCursor; - else if (relativePos > preeditPos) - relativePos += layout->preeditAreaText().length(); - } - QTextLine line = layout->lineForTextPosition(relativePos); - - int cursorWidth; - { - bool ok = false; -#ifndef QT_NO_PROPERTIES - cursorWidth = docLayout->property("cursorWidth").toInt(&ok); -#endif - if (!ok) - cursorWidth = 1; - } - - QRectF r; - - if (line.isValid()) { - qreal x = line.cursorToX(relativePos); - qreal w = 0; - if (overwriteMode) { - if (relativePos < line.textLength() - line.textStart()) - w = line.cursorToX(relativePos + 1) - x; - else - w = QFontMetrics(block.layout()->font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw() - } - r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(), - cursorWidth + w, line.height()); - } else { - r = QRectF(layoutPos.x(), layoutPos.y(), cursorWidth, 10); // #### correct height - } - - return r; -} - -static inline bool firstFramePosLessThanCursorPos(QTextFrame *frame, int position) -{ - return frame->firstPosition() < position; -} - -static inline bool cursorPosLessThanLastFramePos(int position, QTextFrame *frame) -{ - return position < frame->lastPosition(); -} - -static QRectF boundingRectOfFloatsInSelection(const QTextCursor &cursor) -{ - QRectF r; - QTextFrame *frame = cursor.currentFrame(); - const QList<QTextFrame *> children = frame->childFrames(); - - const QList<QTextFrame *>::ConstIterator firstFrame = qLowerBound(children.constBegin(), children.constEnd(), - cursor.selectionStart(), firstFramePosLessThanCursorPos); - const QList<QTextFrame *>::ConstIterator lastFrame = qUpperBound(children.constBegin(), children.constEnd(), - cursor.selectionEnd(), cursorPosLessThanLastFramePos); - for (QList<QTextFrame *>::ConstIterator it = firstFrame; it != lastFrame; ++it) { - if ((*it)->frameFormat().position() != QTextFrameFormat::InFlow) - r |= frame->document()->documentLayout()->frameBoundingRect(*it); - } - return r; -} - -QRectF QTextControl::selectionRect(const QTextCursor &cursor) const -{ - Q_D(const QTextControl); - - QRectF r = d->rectForPosition(cursor.selectionStart()); - - if (cursor.hasComplexSelection() && cursor.currentTable()) { - QTextTable *table = cursor.currentTable(); - - r = d->doc->documentLayout()->frameBoundingRect(table); - /* - int firstRow, numRows, firstColumn, numColumns; - cursor.selectedTableCells(&firstRow, &numRows, &firstColumn, &numColumns); - - const QTextTableCell firstCell = table->cellAt(firstRow, firstColumn); - const QTextTableCell lastCell = table->cellAt(firstRow + numRows - 1, firstColumn + numColumns - 1); - - const QAbstractTextDocumentLayout * const layout = doc->documentLayout(); - - QRectF tableSelRect = layout->blockBoundingRect(firstCell.firstCursorPosition().block()); - - for (int col = firstColumn; col < firstColumn + numColumns; ++col) { - const QTextTableCell cell = table->cellAt(firstRow, col); - const qreal y = layout->blockBoundingRect(cell.firstCursorPosition().block()).top(); - - tableSelRect.setTop(qMin(tableSelRect.top(), y)); - } - - for (int row = firstRow; row < firstRow + numRows; ++row) { - const QTextTableCell cell = table->cellAt(row, firstColumn); - const qreal x = layout->blockBoundingRect(cell.firstCursorPosition().block()).left(); - - tableSelRect.setLeft(qMin(tableSelRect.left(), x)); - } - - for (int col = firstColumn; col < firstColumn + numColumns; ++col) { - const QTextTableCell cell = table->cellAt(firstRow + numRows - 1, col); - const qreal y = layout->blockBoundingRect(cell.lastCursorPosition().block()).bottom(); - - tableSelRect.setBottom(qMax(tableSelRect.bottom(), y)); - } - - for (int row = firstRow; row < firstRow + numRows; ++row) { - const QTextTableCell cell = table->cellAt(row, firstColumn + numColumns - 1); - const qreal x = layout->blockBoundingRect(cell.lastCursorPosition().block()).right(); - - tableSelRect.setRight(qMax(tableSelRect.right(), x)); - } - - r = tableSelRect.toRect(); - */ - } else if (cursor.hasSelection()) { - const int position = cursor.selectionStart(); - const int anchor = cursor.selectionEnd(); - const QTextBlock posBlock = d->doc->findBlock(position); - const QTextBlock anchorBlock = d->doc->findBlock(anchor); - if (posBlock == anchorBlock && posBlock.isValid() && posBlock.layout()->lineCount()) { - const QTextLine posLine = posBlock.layout()->lineForTextPosition(position - posBlock.position()); - const QTextLine anchorLine = anchorBlock.layout()->lineForTextPosition(anchor - anchorBlock.position()); - - const int firstLine = qMin(posLine.lineNumber(), anchorLine.lineNumber()); - const int lastLine = qMax(posLine.lineNumber(), anchorLine.lineNumber()); - const QTextLayout *layout = posBlock.layout(); - r = QRectF(); - for (int i = firstLine; i <= lastLine; ++i) { - r |= layout->lineAt(i).rect(); - r |= layout->lineAt(i).naturalTextRect(); // might be bigger in the case of wrap not enabled - } - r.translate(blockBoundingRect(posBlock).topLeft()); - } else { - QRectF anchorRect = d->rectForPosition(cursor.selectionEnd()); - r |= anchorRect; - r |= boundingRectOfFloatsInSelection(cursor); - QRectF frameRect(d->doc->documentLayout()->frameBoundingRect(cursor.currentFrame())); - r.setLeft(frameRect.left()); - r.setRight(frameRect.right()); - } - if (r.isValid()) - r.adjust(-1, -1, 1, 1); - } - - return r; -} - -QRectF QTextControl::selectionRect() const -{ - Q_D(const QTextControl); - return selectionRect(d->cursor); -} - -void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, const QPoint &globalPos) -{ - Q_Q(QTextControl); - - if (sendMouseEventToInputContext( - e, QEvent::MouseButtonPress, button, pos, modifiers, buttons, globalPos)) { - return; - } - - if (interactionFlags & Qt::LinksAccessibleByMouse) { - anchorOnMousePress = q->anchorAt(pos); - - if (cursorIsFocusIndicator) { - cursorIsFocusIndicator = false; - repaintSelection(); - cursor.clearSelection(); - } - } - if (!(button & Qt::LeftButton) || - !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) { - e->ignore(); - return; - } - - cursorIsFocusIndicator = false; - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - - mousePressed = (interactionFlags & Qt::TextSelectableByMouse); -#ifndef QT_NO_DRAGANDDROP - mightStartDrag = false; -#endif - - if (trippleClickTimer.isActive() - && ((pos - trippleClickPoint).toPoint().manhattanLength() < QApplication::startDragDistance())) { - - cursor.movePosition(QTextCursor::StartOfBlock); - cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); - selectedBlockOnTrippleClick = cursor; - - anchorOnMousePress = QString(); - - trippleClickTimer.stop(); - } else { - int cursorPos = q->hitTest(pos, Qt::FuzzyHit); - if (cursorPos == -1) { - e->ignore(); - return; - } - - if (modifiers == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) { - if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { - selectedWordOnDoubleClick = cursor; - selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); - } - - if (selectedBlockOnTrippleClick.hasSelection()) - extendBlockwiseSelection(cursorPos); - else if (selectedWordOnDoubleClick.hasSelection()) - extendWordwiseSelection(cursorPos, pos.x()); - else if (!wordSelectionEnabled) - setCursorPosition(cursorPos, QTextCursor::KeepAnchor); - } else { - - if (dragEnabled - && cursor.hasSelection() - && !cursorIsFocusIndicator - && cursorPos >= cursor.selectionStart() - && cursorPos <= cursor.selectionEnd() - && q->hitTest(pos, Qt::ExactHit) != -1) { -#ifndef QT_NO_DRAGANDDROP - mightStartDrag = true; - dragStartPos = pos.toPoint(); -#endif - return; - } - - setCursorPosition(cursorPos); - } - } - - if (interactionFlags & Qt::TextEditable) { - q->ensureCursorVisible(); - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - _q_updateCurrentCharFormatAndSelection(); - } else { - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - selectionChanged(); - } - repaintOldAndNewSelection(oldSelection); - hadSelectionOnMousePress = cursor.hasSelection(); -} - -void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &mousePos, Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, const QPoint &globalPos) -{ - Q_Q(QTextControl); - - if (sendMouseEventToInputContext( - e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos)) { - return; - } - - if (interactionFlags & Qt::LinksAccessibleByMouse) { - QString anchor = q->anchorAt(mousePos); - if (anchor != highlightedAnchor) { - highlightedAnchor = anchor; - emit q->linkHovered(anchor); - } - } - - if (!(buttons & Qt::LeftButton)) - return; - - const bool editable = interactionFlags & Qt::TextEditable; - - if (!(mousePressed - || editable - || mightStartDrag - || selectedWordOnDoubleClick.hasSelection() - || selectedBlockOnTrippleClick.hasSelection())) - return; - - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - - if (mightStartDrag) { - if ((mousePos.toPoint() - dragStartPos).manhattanLength() > QApplication::startDragDistance()) - startDrag(); - return; - } - - if (!mousePressed) - return; - - const qreal mouseX = qreal(mousePos.x()); - - int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit); - if (newCursorPos == -1) - return; - - if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { - selectedWordOnDoubleClick = cursor; - selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); - } - - if (selectedBlockOnTrippleClick.hasSelection()) - extendBlockwiseSelection(newCursorPos); - else if (selectedWordOnDoubleClick.hasSelection()) - extendWordwiseSelection(newCursorPos, mouseX); - else - setCursorPosition(newCursorPos, QTextCursor::KeepAnchor); - - if (interactionFlags & Qt::TextEditable) { - // don't call ensureVisible for the visible cursor to avoid jumping - // scrollbars. the autoscrolling ensures smooth scrolling if necessary. - //q->ensureCursorVisible(); - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - _q_updateCurrentCharFormatAndSelection(); -#ifndef QT_NO_IM - if (contextWidget) { - if (QInputContext *ic = inputContext()) { - ic->update(); - } - } -#endif //QT_NO_IM - } else { - //emit q->visibilityRequest(QRectF(mousePos, QSizeF(1, 1))); - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - } - selectionChanged(true); - repaintOldAndNewSelection(oldSelection); -} - -void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, const QPoint &globalPos) -{ - Q_Q(QTextControl); - - if (sendMouseEventToInputContext( - e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) { - return; - } - - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - -#ifndef QT_NO_DRAGANDDROP - if (mightStartDrag && (button & Qt::LeftButton)) { - mousePressed = false; - setCursorPosition(pos); - cursor.clearSelection(); - selectionChanged(); - } -#endif - if (mousePressed) { - mousePressed = false; -#ifndef QT_NO_CLIPBOARD - setClipboardSelection(); - selectionChanged(true); - } else if (button == Qt::MidButton - && (interactionFlags & Qt::TextEditable) - && QApplication::clipboard()->supportsSelection()) { - setCursorPosition(pos); - const QMimeData *md = QApplication::clipboard()->mimeData(QClipboard::Selection); - if (md) - q->insertFromMimeData(md); -#endif - } - - repaintOldAndNewSelection(oldSelection); - - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - - if (interactionFlags & Qt::LinksAccessibleByMouse) { - if (!(button & Qt::LeftButton)) - return; - - const QString anchor = q->anchorAt(pos); - - if (anchor.isEmpty()) - return; - - if (!cursor.hasSelection() - || (anchor == anchorOnMousePress && hadSelectionOnMousePress)) { - - const int anchorPos = q->hitTest(pos, Qt::ExactHit); - if (anchorPos != -1) { - cursor.setPosition(anchorPos); - - QString anchor = anchorOnMousePress; - anchorOnMousePress = QString(); - activateLinkUnderCursor(anchor); - } - } - } -} - -void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, const QPoint &globalPos) -{ - Q_Q(QTextControl); - - if (sendMouseEventToInputContext( - e, QEvent::MouseButtonDblClick, button, pos, modifiers, buttons, globalPos)) { - return; - } - - if (button != Qt::LeftButton - || !(interactionFlags & Qt::TextSelectableByMouse)) { - e->ignore(); - return; - } - -#ifndef QT_NO_DRAGANDDROP - mightStartDrag = false; -#endif - const QTextCursor oldSelection = cursor; - setCursorPosition(pos); - QTextLine line = currentTextLine(cursor); - bool doEmit = false; - if (line.isValid() && line.textLength()) { - cursor.select(QTextCursor::WordUnderCursor); - doEmit = true; - } - repaintOldAndNewSelection(oldSelection); - - cursorIsFocusIndicator = false; - selectedWordOnDoubleClick = cursor; - - trippleClickPoint = pos; - trippleClickTimer.start(QApplication::doubleClickInterval(), q); - if (doEmit) { - selectionChanged(); -#ifndef QT_NO_CLIPBOARD - setClipboardSelection(); -#endif - emit q->cursorPositionChanged(); - } -} - -bool QTextControlPrivate::sendMouseEventToInputContext( - QEvent *e, QEvent::Type eventType, Qt::MouseButton button, const QPointF &pos, - Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos) -{ -#if !defined(QT_NO_IM) - Q_Q(QTextControl); - - QTextLayout *layout = cursor.block().layout(); - if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { - QInputContext *ctx = inputContext(); - int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position(); - - if (cursorPos < 0 || cursorPos > layout->preeditAreaText().length()) { - cursorPos = -1; - // don't send move events outside the preedit area - if (eventType == QEvent::MouseMove) - return true; - } - if (ctx) { - QMouseEvent ev(eventType, contextWidget->mapFromGlobal(globalPos), globalPos, - button, buttons, modifiers); - ctx->mouseHandler(cursorPos, &ev); - e->setAccepted(ev.isAccepted()); - } - if (!layout->preeditAreaText().isEmpty()) - return true; - } -#else - Q_UNUSED(e); - Q_UNUSED(eventType); - Q_UNUSED(button); - Q_UNUSED(pos); - Q_UNUSED(modifiers); - Q_UNUSED(buttons); - Q_UNUSED(globalPos); -#endif - return false; -} - -void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget) -{ -#ifdef QT_NO_CONTEXTMENU - Q_UNUSED(screenPos); - Q_UNUSED(docPos); - Q_UNUSED(contextWidget); -#else - Q_Q(QTextControl); - if (!hasFocus) - return; - QMenu *menu = q->createStandardContextMenu(docPos, contextWidget); - if (!menu) - return; - menu->setAttribute(Qt::WA_DeleteOnClose); - menu->popup(screenPos); -#endif -} - -bool QTextControlPrivate::dragEnterEvent(QEvent *e, const QMimeData *mimeData) -{ - Q_Q(QTextControl); - if (!(interactionFlags & Qt::TextEditable) || !q->canInsertFromMimeData(mimeData)) { - e->ignore(); - return false; - } - - dndFeedbackCursor = QTextCursor(); - - return true; // accept proposed action -} - -void QTextControlPrivate::dragLeaveEvent() -{ - Q_Q(QTextControl); - - const QRectF crect = q->cursorRect(dndFeedbackCursor); - dndFeedbackCursor = QTextCursor(); - - if (crect.isValid()) - emit q->updateRequest(crect); -} - -bool QTextControlPrivate::dragMoveEvent(QEvent *e, const QMimeData *mimeData, const QPointF &pos) -{ - Q_Q(QTextControl); - if (!(interactionFlags & Qt::TextEditable) || !q->canInsertFromMimeData(mimeData)) { - e->ignore(); - return false; - } - - const int cursorPos = q->hitTest(pos, Qt::FuzzyHit); - if (cursorPos != -1) { - QRectF crect = q->cursorRect(dndFeedbackCursor); - if (crect.isValid()) - emit q->updateRequest(crect); - - dndFeedbackCursor = cursor; - dndFeedbackCursor.setPosition(cursorPos); - - crect = q->cursorRect(dndFeedbackCursor); - emit q->updateRequest(crect); - } - - return true; // accept proposed action -} - -bool QTextControlPrivate::dropEvent(const QMimeData *mimeData, const QPointF &pos, Qt::DropAction dropAction, QWidget *source) -{ - Q_Q(QTextControl); - dndFeedbackCursor = QTextCursor(); - - if (!(interactionFlags & Qt::TextEditable) || !q->canInsertFromMimeData(mimeData)) - return false; - - repaintSelection(); - - QTextCursor insertionCursor = q->cursorForPosition(pos); - insertionCursor.beginEditBlock(); - - if (dropAction == Qt::MoveAction && source == contextWidget) - cursor.removeSelectedText(); - - cursor = insertionCursor; - q->insertFromMimeData(mimeData); - insertionCursor.endEditBlock(); - q->ensureCursorVisible(); - return true; // accept proposed action -} - -void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) -{ - Q_Q(QTextControl); - if (!(interactionFlags & Qt::TextEditable) || cursor.isNull()) { - e->ignore(); - return; - } - bool isGettingInput = !e->commitString().isEmpty() - || e->preeditString() != cursor.block().layout()->preeditAreaText() - || e->replacementLength() > 0; - - cursor.beginEditBlock(); - if (isGettingInput) { - cursor.removeSelectedText(); - } - - // insert commit string - if (!e->commitString().isEmpty() || e->replacementLength()) { - QTextCursor c = cursor; - c.setPosition(c.position() + e->replacementStart()); - c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor); - c.insertText(e->commitString()); - } - - for (int i = 0; i < e->attributes().size(); ++i) { - const QInputMethodEvent::Attribute &a = e->attributes().at(i); - if (a.type == QInputMethodEvent::Selection) { - QTextCursor oldCursor = cursor; - int blockStart = a.start + cursor.block().position(); - cursor.setPosition(blockStart, QTextCursor::MoveAnchor); - cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor); - q->ensureCursorVisible(); - repaintOldAndNewSelection(oldCursor); - } - } - - QTextBlock block = cursor.block(); - QTextLayout *layout = block.layout(); - if (isGettingInput) - layout->setPreeditArea(cursor.position() - block.position(), e->preeditString()); - QList<QTextLayout::FormatRange> overrides; - const int oldPreeditCursor = preeditCursor; - preeditCursor = e->preeditString().length(); - hideCursor = false; - for (int i = 0; i < e->attributes().size(); ++i) { - const QInputMethodEvent::Attribute &a = e->attributes().at(i); - if (a.type == QInputMethodEvent::Cursor) { - preeditCursor = a.start; - hideCursor = !a.length; - } else if (a.type == QInputMethodEvent::TextFormat) { - QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat(); - if (f.isValid()) { - QTextLayout::FormatRange o; - o.start = a.start + cursor.position() - block.position(); - o.length = a.length; - o.format = f; - overrides.append(o); - } - } - } - layout->setAdditionalFormats(overrides); - cursor.endEditBlock(); - if (cursor.d) - cursor.d->setX(); - if (oldPreeditCursor != preeditCursor) - emit q->microFocusChanged(); -} - -QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const -{ - Q_D(const QTextControl); - QTextBlock block = d->cursor.block(); - switch(property) { - case Qt::ImMicroFocus: - return cursorRect(); - case Qt::ImFont: - return QVariant(d->cursor.charFormat().font()); - case Qt::ImCursorPosition: - return QVariant(d->cursor.position() - block.position()); - case Qt::ImSurroundingText: - return QVariant(block.text()); - case Qt::ImCurrentSelection: - return QVariant(d->cursor.selectedText()); - case Qt::ImMaximumTextLength: - return QVariant(); // No limit. - case Qt::ImAnchorPosition: - return QVariant(qBound(0, d->cursor.anchor() - block.position(), block.length())); - default: - return QVariant(); - } -} - -void QTextControl::setFocus(bool focus, Qt::FocusReason reason) -{ - QFocusEvent ev(focus ? QEvent::FocusIn : QEvent::FocusOut, - reason); - processEvent(&ev); -} - -void QTextControlPrivate::focusEvent(QFocusEvent *e) -{ - Q_Q(QTextControl); - emit q->updateRequest(q->selectionRect()); - if (e->gotFocus()) { -#ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || (hasEditFocus && (e->reason() == Qt::PopupFocusReason -#ifdef Q_OS_SYMBIAN - || e->reason() == Qt::ActiveWindowFocusReason -#endif - ))) { -#endif - cursorOn = (interactionFlags & Qt::TextSelectableByKeyboard); - if (interactionFlags & Qt::TextEditable) { - setBlinkingCursorEnabled(true); - } -#ifdef QT_KEYPAD_NAVIGATION - } -#endif - } else { - setBlinkingCursorEnabled(false); - - if (cursorIsFocusIndicator - && e->reason() != Qt::ActiveWindowFocusReason - && e->reason() != Qt::PopupFocusReason - && cursor.hasSelection()) { - cursor.clearSelection(); - } - } - hasFocus = e->gotFocus(); -} - -QString QTextControlPrivate::anchorForCursor(const QTextCursor &anchorCursor) const -{ - if (anchorCursor.hasSelection()) { - QTextCursor cursor = anchorCursor; - if (cursor.selectionStart() != cursor.position()) - cursor.setPosition(cursor.selectionStart()); - cursor.movePosition(QTextCursor::NextCharacter); - QTextCharFormat fmt = cursor.charFormat(); - if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) - return fmt.stringProperty(QTextFormat::AnchorHref); - } - return QString(); -} - -#ifdef QT_KEYPAD_NAVIGATION -void QTextControlPrivate::editFocusEvent(QEvent *e) -{ - Q_Q(QTextControl); - - if (QApplication::keypadNavigationEnabled()) { - if (e->type() == QEvent::EnterEditFocus && interactionFlags & Qt::TextEditable) { - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - const bool moved = cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); - q->ensureCursorVisible(); - if (moved) { - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - emit q->microFocusChanged(); - } - selectionChanged(); - repaintOldAndNewSelection(oldSelection); - - setBlinkingCursorEnabled(true); - } else - setBlinkingCursorEnabled(false); - } - - hasEditFocus = e->type() == QEvent::EnterEditFocus ? true : false; -} -#endif - -#ifndef QT_NO_CONTEXTMENU -QMenu *QTextControl::createStandardContextMenu(const QPointF &pos, QWidget *parent) -{ - Q_D(QTextControl); - - const bool showTextSelectionActions = d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse); - - d->linkToCopy = QString(); - if (!pos.isNull()) - d->linkToCopy = anchorAt(pos); - - if (d->linkToCopy.isEmpty() && !showTextSelectionActions) - return 0; - - QMenu *menu = new QMenu(parent); - QAction *a; - - if (d->interactionFlags & Qt::TextEditable) { - a = menu->addAction(tr("&Undo") + ACCEL_KEY(QKeySequence::Undo), this, SLOT(undo())); - a->setEnabled(d->doc->isUndoAvailable()); - a = menu->addAction(tr("&Redo") + ACCEL_KEY(QKeySequence::Redo), this, SLOT(redo())); - a->setEnabled(d->doc->isRedoAvailable()); - menu->addSeparator(); - - a = menu->addAction(tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut), this, SLOT(cut())); - a->setEnabled(d->cursor.hasSelection()); - } - - if (showTextSelectionActions) { - a = menu->addAction(tr("&Copy") + ACCEL_KEY(QKeySequence::Copy), this, SLOT(copy())); - a->setEnabled(d->cursor.hasSelection()); - } - - if ((d->interactionFlags & Qt::LinksAccessibleByKeyboard) - || (d->interactionFlags & Qt::LinksAccessibleByMouse)) { - - a = menu->addAction(tr("Copy &Link Location"), this, SLOT(_q_copyLink())); - a->setEnabled(!d->linkToCopy.isEmpty()); - } - - if (d->interactionFlags & Qt::TextEditable) { -#if !defined(QT_NO_CLIPBOARD) - a = menu->addAction(tr("&Paste") + ACCEL_KEY(QKeySequence::Paste), this, SLOT(paste())); - a->setEnabled(canPaste()); -#endif - a = menu->addAction(tr("Delete"), this, SLOT(_q_deleteSelected())); - a->setEnabled(d->cursor.hasSelection()); - } - - - if (showTextSelectionActions) { - menu->addSeparator(); - a = menu->addAction(tr("Select All") + ACCEL_KEY(QKeySequence::SelectAll), this, SLOT(selectAll())); - a->setEnabled(!d->doc->isEmpty()); - } - -#if !defined(QT_NO_IM) - if (d->contextWidget) { - QInputContext *qic = d->inputContext(); - if (qic) { - QList<QAction *> imActions = qic->actions(); - for (int i = 0; i < imActions.size(); ++i) - menu->addAction(imActions.at(i)); - } - } -#endif - -#if defined(Q_WS_WIN) || defined(Q_WS_X11) - if ((d->interactionFlags & Qt::TextEditable) && qt_use_rtl_extensions) { -#else - if (d->interactionFlags & Qt::TextEditable) { -#endif - menu->addSeparator(); - QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, menu); - menu->addMenu(ctrlCharacterMenu); - } - - return menu; -} -#endif // QT_NO_CONTEXTMENU - -QTextCursor QTextControl::cursorForPosition(const QPointF &pos) const -{ - Q_D(const QTextControl); - int cursorPos = hitTest(pos, Qt::FuzzyHit); - if (cursorPos == -1) - cursorPos = 0; - QTextCursor c(d->doc); - c.setPosition(cursorPos); - return c; -} - -QRectF QTextControl::cursorRect(const QTextCursor &cursor) const -{ - Q_D(const QTextControl); - if (cursor.isNull()) - return QRectF(); - - return d->rectForPosition(cursor.position()); -} - -QRectF QTextControl::cursorRect() const -{ - Q_D(const QTextControl); - return cursorRect(d->cursor); -} - -QRectF QTextControlPrivate::cursorRectPlusUnicodeDirectionMarkers(const QTextCursor &cursor) const -{ - if (cursor.isNull()) - return QRectF(); - - return rectForPosition(cursor.position()).adjusted(-4, 0, 4, 0); -} - -QString QTextControl::anchorAt(const QPointF &pos) const -{ - Q_D(const QTextControl); - return d->doc->documentLayout()->anchorAt(pos); -} - -QString QTextControl::anchorAtCursor() const -{ - Q_D(const QTextControl); - - return d->anchorForCursor(d->cursor); -} - -bool QTextControl::overwriteMode() const -{ - Q_D(const QTextControl); - return d->overwriteMode; -} - -void QTextControl::setOverwriteMode(bool overwrite) -{ - Q_D(QTextControl); - d->overwriteMode = overwrite; -} - -int QTextControl::cursorWidth() const -{ -#ifndef QT_NO_PROPERTIES - Q_D(const QTextControl); - return d->doc->documentLayout()->property("cursorWidth").toInt(); -#else - return 1; -#endif -} - -void QTextControl::setCursorWidth(int width) -{ - Q_D(QTextControl); -#ifdef QT_NO_PROPERTIES - Q_UNUSED(width); -#else - if (width == -1) - width = QApplication::style()->pixelMetric(QStyle::PM_TextCursorWidth); - d->doc->documentLayout()->setProperty("cursorWidth", width); -#endif - d->repaintCursor(); -} - -bool QTextControl::acceptRichText() const -{ - Q_D(const QTextControl); - return d->acceptRichText; -} - -void QTextControl::setAcceptRichText(bool accept) -{ - Q_D(QTextControl); - d->acceptRichText = accept; -} - -#ifndef QT_NO_TEXTEDIT - -void QTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelection> &selections) -{ - Q_D(QTextControl); - - QHash<int, int> hash; - for (int i = 0; i < d->extraSelections.count(); ++i) { - const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(i); - hash.insertMulti(esel.cursor.anchor(), i); - } - - for (int i = 0; i < selections.count(); ++i) { - const QTextEdit::ExtraSelection &sel = selections.at(i); - QHash<int, int>::iterator it = hash.find(sel.cursor.anchor()); - if (it != hash.end()) { - const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(it.value()); - if (esel.cursor.position() == sel.cursor.position() - && esel.format == sel.format) { - hash.erase(it); - continue; - } - } - QRectF r = selectionRect(sel.cursor); - if (sel.format.boolProperty(QTextFormat::FullWidthSelection)) { - r.setLeft(0); - r.setWidth(qreal(INT_MAX)); - } - emit updateRequest(r); - } - - for (QHash<int, int>::iterator it = hash.begin(); it != hash.end(); ++it) { - const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(it.value()); - QRectF r = selectionRect(esel.cursor); - if (esel.format.boolProperty(QTextFormat::FullWidthSelection)) { - r.setLeft(0); - r.setWidth(qreal(INT_MAX)); - } - emit updateRequest(r); - } - - d->extraSelections.resize(selections.count()); - for (int i = 0; i < selections.count(); ++i) { - d->extraSelections[i].cursor = selections.at(i).cursor; - d->extraSelections[i].format = selections.at(i).format; - } -} - -QList<QTextEdit::ExtraSelection> QTextControl::extraSelections() const -{ - Q_D(const QTextControl); - QList<QTextEdit::ExtraSelection> selections; - for (int i = 0; i < d->extraSelections.count(); ++i) { - QTextEdit::ExtraSelection sel; - sel.cursor = d->extraSelections.at(i).cursor; - sel.format = d->extraSelections.at(i).format; - selections.append(sel); - } - return selections; -} - -#endif // QT_NO_TEXTEDIT - -void QTextControl::setTextWidth(qreal width) -{ - Q_D(QTextControl); - d->doc->setTextWidth(width); -} - -qreal QTextControl::textWidth() const -{ - Q_D(const QTextControl); - return d->doc->textWidth(); -} - -QSizeF QTextControl::size() const -{ - Q_D(const QTextControl); - return d->doc->size(); -} - -void QTextControl::setOpenExternalLinks(bool open) -{ - Q_D(QTextControl); - d->openExternalLinks = open; -} - -bool QTextControl::openExternalLinks() const -{ - Q_D(const QTextControl); - return d->openExternalLinks; -} - -bool QTextControl::ignoreUnusedNavigationEvents() const -{ - Q_D(const QTextControl); - return d->ignoreUnusedNavigationEvents; -} - -void QTextControl::setIgnoreUnusedNavigationEvents(bool ignore) -{ - Q_D(QTextControl); - d->ignoreUnusedNavigationEvents = ignore; -} - -void QTextControl::moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode) -{ - Q_D(QTextControl); - const QTextCursor oldSelection = d->cursor; - const bool moved = d->cursor.movePosition(op, mode); - d->_q_updateCurrentCharFormatAndSelection(); - ensureCursorVisible(); - d->repaintOldAndNewSelection(oldSelection); - if (moved) - emit cursorPositionChanged(); -} - -bool QTextControl::canPaste() const -{ -#ifndef QT_NO_CLIPBOARD - Q_D(const QTextControl); - if (d->interactionFlags & Qt::TextEditable) { - const QMimeData *md = QApplication::clipboard()->mimeData(); - return md && canInsertFromMimeData(md); - } -#endif - return false; -} - -void QTextControl::setCursorIsFocusIndicator(bool b) -{ - Q_D(QTextControl); - d->cursorIsFocusIndicator = b; - d->repaintCursor(); -} - -bool QTextControl::cursorIsFocusIndicator() const -{ - Q_D(const QTextControl); - return d->cursorIsFocusIndicator; -} - - -void QTextControl::setDragEnabled(bool enabled) -{ - Q_D(QTextControl); - d->dragEnabled = enabled; -} - -bool QTextControl::isDragEnabled() const -{ - Q_D(const QTextControl); - return d->dragEnabled; -} - -void QTextControl::setWordSelectionEnabled(bool enabled) -{ - Q_D(QTextControl); - d->wordSelectionEnabled = enabled; -} - -bool QTextControl::isWordSelectionEnabled() const -{ - Q_D(const QTextControl); - return d->wordSelectionEnabled; -} - -#ifndef QT_NO_PRINTER -void QTextControl::print(QPrinter *printer) const -{ -#ifndef QT_NO_PRINTER - Q_D(const QTextControl); - if (!printer || !printer->isValid()) - return; - QTextDocument *tempDoc = 0; - const QTextDocument *doc = d->doc; - if (printer->printRange() == QPrinter::Selection) { - if (!d->cursor.hasSelection()) - return; - tempDoc = new QTextDocument(const_cast<QTextDocument *>(doc)); - tempDoc->setMetaInformation(QTextDocument::DocumentTitle, doc->metaInformation(QTextDocument::DocumentTitle)); - tempDoc->setPageSize(doc->pageSize()); - tempDoc->setDefaultFont(doc->defaultFont()); - tempDoc->setUseDesignMetrics(doc->useDesignMetrics()); - QTextCursor(tempDoc).insertFragment(d->cursor.selection()); - doc = tempDoc; - - // copy the custom object handlers - doc->documentLayout()->d_func()->handlers = d->doc->documentLayout()->d_func()->handlers; - } - doc->print(printer); - delete tempDoc; -#endif -} -#endif // QT_NO_PRINTER - -QMimeData *QTextControl::createMimeDataFromSelection() const -{ - Q_D(const QTextControl); - const QTextDocumentFragment fragment(d->cursor); - return new QTextEditMimeData(fragment); -} - -bool QTextControl::canInsertFromMimeData(const QMimeData *source) const -{ - Q_D(const QTextControl); - if (d->acceptRichText) - return (source->hasText() && !source->text().isEmpty()) - || source->hasHtml() - || source->hasFormat(QLatin1String("application/x-qrichtext")) - || source->hasFormat(QLatin1String("application/x-qt-richtext")); - else - return source->hasText() && !source->text().isEmpty(); -} - -void QTextControl::insertFromMimeData(const QMimeData *source) -{ - Q_D(QTextControl); - if (!(d->interactionFlags & Qt::TextEditable) || !source) - return; - - bool hasData = false; - QTextDocumentFragment fragment; -#ifndef QT_NO_TEXTHTMLPARSER - if (source->hasFormat(QLatin1String("application/x-qrichtext")) && d->acceptRichText) { - // x-qrichtext is always UTF-8 (taken from Qt3 since we don't use it anymore). - QString richtext = QString::fromUtf8(source->data(QLatin1String("application/x-qrichtext"))); - richtext.prepend(QLatin1String("<meta name=\"qrichtext\" content=\"1\" />")); - fragment = QTextDocumentFragment::fromHtml(richtext, d->doc); - hasData = true; - } else if (source->hasHtml() && d->acceptRichText) { - fragment = QTextDocumentFragment::fromHtml(source->html(), d->doc); - hasData = true; - } else { - QString text = source->text(); - if (!text.isNull()) { - fragment = QTextDocumentFragment::fromPlainText(text); - hasData = true; - } - } -#else - fragment = QTextDocumentFragment::fromPlainText(source->text()); -#endif // QT_NO_TEXTHTMLPARSER - - if (hasData) - d->cursor.insertFragment(fragment); - ensureCursorVisible(); -} - -bool QTextControl::findNextPrevAnchor(const QTextCursor &startCursor, bool next, QTextCursor &newAnchor) -{ - Q_D(QTextControl); - - int anchorStart = -1; - QString anchorHref; - int anchorEnd = -1; - - if (next) { - const int startPos = startCursor.selectionEnd(); - - QTextBlock block = d->doc->findBlock(startPos); - QTextBlock::Iterator it = block.begin(); - - while (!it.atEnd() && it.fragment().position() < startPos) - ++it; - - while (block.isValid()) { - anchorStart = -1; - - // find next anchor - for (; !it.atEnd(); ++it) { - const QTextFragment fragment = it.fragment(); - const QTextCharFormat fmt = fragment.charFormat(); - - if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) { - anchorStart = fragment.position(); - anchorHref = fmt.anchorHref(); - break; - } - } - - if (anchorStart != -1) { - anchorEnd = -1; - - // find next non-anchor fragment - for (; !it.atEnd(); ++it) { - const QTextFragment fragment = it.fragment(); - const QTextCharFormat fmt = fragment.charFormat(); - - if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) { - anchorEnd = fragment.position(); - break; - } - } - - if (anchorEnd == -1) - anchorEnd = block.position() + block.length() - 1; - - // make found selection - break; - } - - block = block.next(); - it = block.begin(); - } - } else { - int startPos = startCursor.selectionStart(); - if (startPos > 0) - --startPos; - - QTextBlock block = d->doc->findBlock(startPos); - QTextBlock::Iterator blockStart = block.begin(); - QTextBlock::Iterator it = block.end(); - - if (startPos == block.position()) { - it = block.begin(); - } else { - do { - if (it == blockStart) { - it = QTextBlock::Iterator(); - block = QTextBlock(); - } else { - --it; - } - } while (!it.atEnd() && it.fragment().position() + it.fragment().length() - 1 > startPos); - } - - while (block.isValid()) { - anchorStart = -1; - - if (!it.atEnd()) { - do { - const QTextFragment fragment = it.fragment(); - const QTextCharFormat fmt = fragment.charFormat(); - - if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) { - anchorStart = fragment.position() + fragment.length(); - anchorHref = fmt.anchorHref(); - break; - } - - if (it == blockStart) - it = QTextBlock::Iterator(); - else - --it; - } while (!it.atEnd()); - } - - if (anchorStart != -1 && !it.atEnd()) { - anchorEnd = -1; - - do { - const QTextFragment fragment = it.fragment(); - const QTextCharFormat fmt = fragment.charFormat(); - - if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) { - anchorEnd = fragment.position() + fragment.length(); - break; - } - - if (it == blockStart) - it = QTextBlock::Iterator(); - else - --it; - } while (!it.atEnd()); - - if (anchorEnd == -1) - anchorEnd = qMax(0, block.position()); - - break; - } - - block = block.previous(); - it = block.end(); - if (it != block.begin()) - --it; - blockStart = block.begin(); - } - - } - - if (anchorStart != -1 && anchorEnd != -1) { - newAnchor = d->cursor; - newAnchor.setPosition(anchorStart); - newAnchor.setPosition(anchorEnd, QTextCursor::KeepAnchor); - return true; - } - - return false; -} - -void QTextControlPrivate::activateLinkUnderCursor(QString href) -{ - QTextCursor oldCursor = cursor; - - if (href.isEmpty()) { - QTextCursor tmp = cursor; - if (tmp.selectionStart() != tmp.position()) - tmp.setPosition(tmp.selectionStart()); - tmp.movePosition(QTextCursor::NextCharacter); - href = tmp.charFormat().anchorHref(); - } - if (href.isEmpty()) - return; - - if (!cursor.hasSelection()) { - QTextBlock block = cursor.block(); - const int cursorPos = cursor.position(); - - QTextBlock::Iterator it = block.begin(); - QTextBlock::Iterator linkFragment; - - for (; !it.atEnd(); ++it) { - QTextFragment fragment = it.fragment(); - const int fragmentPos = fragment.position(); - if (fragmentPos <= cursorPos && - fragmentPos + fragment.length() > cursorPos) { - linkFragment = it; - break; - } - } - - if (!linkFragment.atEnd()) { - it = linkFragment; - cursor.setPosition(it.fragment().position()); - if (it != block.begin()) { - do { - --it; - QTextFragment fragment = it.fragment(); - if (fragment.charFormat().anchorHref() != href) - break; - cursor.setPosition(fragment.position()); - } while (it != block.begin()); - } - - for (it = linkFragment; !it.atEnd(); ++it) { - QTextFragment fragment = it.fragment(); - if (fragment.charFormat().anchorHref() != href) - break; - cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor); - } - } - } - - if (hasFocus) { - cursorIsFocusIndicator = true; - } else { - cursorIsFocusIndicator = false; - cursor.clearSelection(); - } - repaintOldAndNewSelection(oldCursor); - -#ifndef QT_NO_DESKTOPSERVICES - if (openExternalLinks) - QDesktopServices::openUrl(href); - else -#endif - emit q_func()->linkActivated(href); -} - -#ifndef QT_NO_TOOLTIP -void QTextControlPrivate::showToolTip(const QPoint &globalPos, const QPointF &pos, QWidget *contextWidget) -{ - const QString toolTip = q_func()->cursorForPosition(pos).charFormat().toolTip(); - if (toolTip.isEmpty()) - return; - QToolTip::showText(globalPos, toolTip, contextWidget); -} -#endif // QT_NO_TOOLTIP - -bool QTextControl::setFocusToNextOrPreviousAnchor(bool next) -{ - Q_D(QTextControl); - - if (!(d->interactionFlags & Qt::LinksAccessibleByKeyboard)) - return false; - - QRectF crect = selectionRect(); - emit updateRequest(crect); - - // If we don't have a current anchor, we start from the start/end - if (!d->cursor.hasSelection()) { - d->cursor = QTextCursor(d->doc); - if (next) - d->cursor.movePosition(QTextCursor::Start); - else - d->cursor.movePosition(QTextCursor::End); - } - - QTextCursor newAnchor; - if (findNextPrevAnchor(d->cursor, next, newAnchor)) { - d->cursor = newAnchor; - d->cursorIsFocusIndicator = true; - } else { - d->cursor.clearSelection(); - } - - if (d->cursor.hasSelection()) { - crect = selectionRect(); - emit updateRequest(crect); - emit visibilityRequest(crect); - return true; - } else { - return false; - } -} - -bool QTextControl::setFocusToAnchor(const QTextCursor &newCursor) -{ - Q_D(QTextControl); - - if (!(d->interactionFlags & Qt::LinksAccessibleByKeyboard)) - return false; - - // Verify that this is an anchor. - const QString anchorHref = d->anchorForCursor(newCursor); - if (anchorHref.isEmpty()) - return false; - - // and process it - QRectF crect = selectionRect(); - emit updateRequest(crect); - - d->cursor.setPosition(newCursor.selectionStart()); - d->cursor.setPosition(newCursor.selectionEnd(), QTextCursor::KeepAnchor); - d->cursorIsFocusIndicator = true; - - crect = selectionRect(); - emit updateRequest(crect); - emit visibilityRequest(crect); - return true; -} - -void QTextControl::setTextInteractionFlags(Qt::TextInteractionFlags flags) -{ - Q_D(QTextControl); - if (flags == d->interactionFlags) - return; - d->interactionFlags = flags; - - if (d->hasFocus) - d->setBlinkingCursorEnabled(flags & Qt::TextEditable); -} - -Qt::TextInteractionFlags QTextControl::textInteractionFlags() const -{ - Q_D(const QTextControl); - return d->interactionFlags; -} - -void QTextControl::mergeCurrentCharFormat(const QTextCharFormat &modifier) -{ - Q_D(QTextControl); - d->cursor.mergeCharFormat(modifier); - d->updateCurrentCharFormat(); -} - -void QTextControl::setCurrentCharFormat(const QTextCharFormat &format) -{ - Q_D(QTextControl); - d->cursor.setCharFormat(format); - d->updateCurrentCharFormat(); -} - -QTextCharFormat QTextControl::currentCharFormat() const -{ - Q_D(const QTextControl); - return d->cursor.charFormat(); -} - -void QTextControl::insertPlainText(const QString &text) -{ - Q_D(QTextControl); - d->cursor.insertText(text); -} - -#ifndef QT_NO_TEXTHTMLPARSER -void QTextControl::insertHtml(const QString &text) -{ - Q_D(QTextControl); - d->cursor.insertHtml(text); -} -#endif // QT_NO_TEXTHTMLPARSER - -QPointF QTextControl::anchorPosition(const QString &name) const -{ - Q_D(const QTextControl); - if (name.isEmpty()) - return QPointF(); - - QRectF r; - for (QTextBlock block = d->doc->begin(); block.isValid(); block = block.next()) { - QTextCharFormat format = block.charFormat(); - if (format.isAnchor() && format.anchorNames().contains(name)) { - r = d->rectForPosition(block.position()); - break; - } - - for (QTextBlock::Iterator it = block.begin(); !it.atEnd(); ++it) { - QTextFragment fragment = it.fragment(); - format = fragment.charFormat(); - if (format.isAnchor() && format.anchorNames().contains(name)) { - r = d->rectForPosition(fragment.position()); - block = QTextBlock(); - break; - } - } - } - if (!r.isValid()) - return QPointF(); - return QPointF(0, r.top()); -} - -void QTextControl::adjustSize() -{ - Q_D(QTextControl); - d->doc->adjustSize(); -} - -bool QTextControl::find(const QString &exp, QTextDocument::FindFlags options) -{ - Q_D(QTextControl); - QTextCursor search = d->doc->find(exp, d->cursor, options); - if (search.isNull()) - return false; - - setTextCursor(search); - return true; -} - - - -void QTextControlPrivate::append(const QString &text, Qt::TextFormat format) -{ - QTextCursor tmp(doc); - tmp.beginEditBlock(); - tmp.movePosition(QTextCursor::End); - - if (!doc->isEmpty()) - tmp.insertBlock(cursor.blockFormat(), cursor.charFormat()); - else - tmp.setCharFormat(cursor.charFormat()); - - // preserve the char format - QTextCharFormat oldCharFormat = cursor.charFormat(); - -#ifndef QT_NO_TEXTHTMLPARSER - if (format == Qt::RichText || (format == Qt::AutoText && Qt::mightBeRichText(text))) { - tmp.insertHtml(text); - } else { - tmp.insertText(text); - } -#else - tmp.insertText(text); -#endif // QT_NO_TEXTHTMLPARSER - if (!cursor.hasSelection()) - cursor.setCharFormat(oldCharFormat); - - tmp.endEditBlock(); -} - -void QTextControl::append(const QString &text) -{ - Q_D(QTextControl); - d->append(text, Qt::AutoText); -} - -void QTextControl::appendHtml(const QString &html) -{ - Q_D(QTextControl); - d->append(html, Qt::RichText); -} - -void QTextControl::appendPlainText(const QString &text) -{ - Q_D(QTextControl); - d->append(text, Qt::PlainText); -} - - -void QTextControl::ensureCursorVisible() -{ - Q_D(QTextControl); - QRectF crect = d->rectForPosition(d->cursor.position()).adjusted(-5, 0, 5, 0); - emit visibilityRequest(crect); - emit microFocusChanged(); -} - -QPalette QTextControl::palette() const -{ - Q_D(const QTextControl); - return d->palette; -} - -void QTextControl::setPalette(const QPalette &pal) -{ - Q_D(QTextControl); - d->palette = pal; -} - -QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget *widget) const -{ - Q_D(const QTextControl); - - QAbstractTextDocumentLayout::PaintContext ctx; - - ctx.selections = d->extraSelections; - ctx.palette = d->palette; - if (d->cursorOn && d->isEnabled) { - if (d->hideCursor) - ctx.cursorPosition = -1; - else if (d->preeditCursor != 0) - ctx.cursorPosition = - (d->preeditCursor + 2); - else - ctx.cursorPosition = d->cursor.position(); - } - - if (!d->dndFeedbackCursor.isNull()) - ctx.cursorPosition = d->dndFeedbackCursor.position(); -#ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || d->hasEditFocus) -#endif - if (d->cursor.hasSelection()) { - QAbstractTextDocumentLayout::Selection selection; - selection.cursor = d->cursor; - if (d->cursorIsFocusIndicator) { - QStyleOption opt; - opt.palette = ctx.palette; - QStyleHintReturnVariant ret; - QStyle *style = QApplication::style(); - if (widget) - style = widget->style(); - style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret); - selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat(); - } else { - QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive; - selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight)); - selection.format.setForeground(ctx.palette.brush(cg, QPalette::HighlightedText)); - QStyleOption opt; - QStyle *style = QApplication::style(); - if (widget) { - opt.initFrom(widget); - style = widget->style(); - } - if (style->styleHint(QStyle::SH_RichText_FullWidthSelection, &opt, widget)) - selection.format.setProperty(QTextFormat::FullWidthSelection, true); - } - ctx.selections.append(selection); - } - - return ctx; -} - -void QTextControl::drawContents(QPainter *p, const QRectF &rect, QWidget *widget) -{ - Q_D(QTextControl); - p->save(); - QAbstractTextDocumentLayout::PaintContext ctx = getPaintContext(widget); - if (rect.isValid()) - p->setClipRect(rect, Qt::IntersectClip); - ctx.clip = rect; - - d->doc->documentLayout()->draw(p, ctx); - p->restore(); -} - -void QTextControlPrivate::_q_copyLink() -{ -#ifndef QT_NO_CLIPBOARD - QMimeData *md = new QMimeData; - md->setText(linkToCopy); - QApplication::clipboard()->setMimeData(md); -#endif -} - -QInputContext *QTextControlPrivate::inputContext() -{ - QInputContext *ctx = contextWidget->inputContext(); - if (!ctx && contextWidget->parentWidget()) - ctx = contextWidget->parentWidget()->inputContext(); - return ctx; -} - -int QTextControl::hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const -{ - Q_D(const QTextControl); - return d->doc->documentLayout()->hitTest(point, accuracy); -} - -QRectF QTextControl::blockBoundingRect(const QTextBlock &block) const -{ - Q_D(const QTextControl); - return d->doc->documentLayout()->blockBoundingRect(block); -} - -#ifndef QT_NO_CONTEXTMENU -#define NUM_CONTROL_CHARACTERS 10 -const struct QUnicodeControlCharacter { - const char *text; - ushort character; -} qt_controlCharacters[NUM_CONTROL_CHARACTERS] = { - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "LRM Left-to-right mark"), 0x200e }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "RLM Right-to-left mark"), 0x200f }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "ZWJ Zero width joiner"), 0x200d }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "ZWNJ Zero width non-joiner"), 0x200c }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "ZWSP Zero width space"), 0x200b }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "LRE Start of left-to-right embedding"), 0x202a }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "RLE Start of right-to-left embedding"), 0x202b }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "LRO Start of left-to-right override"), 0x202d }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "RLO Start of right-to-left override"), 0x202e }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "PDF Pop directional formatting"), 0x202c }, -}; - -QUnicodeControlCharacterMenu::QUnicodeControlCharacterMenu(QObject *_editWidget, QWidget *parent) - : QMenu(parent), editWidget(_editWidget) -{ - setTitle(tr("Insert Unicode control character")); - for (int i = 0; i < NUM_CONTROL_CHARACTERS; ++i) { - addAction(tr(qt_controlCharacters[i].text), this, SLOT(menuActionTriggered())); - } -} - -void QUnicodeControlCharacterMenu::menuActionTriggered() -{ - QAction *a = qobject_cast<QAction *>(sender()); - int idx = actions().indexOf(a); - if (idx < 0 || idx >= NUM_CONTROL_CHARACTERS) - return; - QChar c(qt_controlCharacters[idx].character); - QString str(c); - -#ifndef QT_NO_TEXTEDIT - if (QTextEdit *edit = qobject_cast<QTextEdit *>(editWidget)) { - edit->insertPlainText(str); - return; - } -#endif - if (QTextControl *control = qobject_cast<QTextControl *>(editWidget)) { - control->insertPlainText(str); - } -#ifndef QT_NO_LINEEDIT - if (QLineEdit *edit = qobject_cast<QLineEdit *>(editWidget)) { - edit->insert(str); - return; - } -#endif -} -#endif // QT_NO_CONTEXTMENU - -QStringList QTextEditMimeData::formats() const -{ - if (!fragment.isEmpty()) - return QStringList() << QString::fromLatin1("text/plain") << QString::fromLatin1("text/html") -#ifndef QT_NO_TEXTODFWRITER - << QString::fromLatin1("application/vnd.oasis.opendocument.text") -#endif - ; - 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); -#ifndef QT_NO_TEXTHTMLPARSER - that->setData(QLatin1String("text/html"), fragment.toHtml("utf-8").toUtf8()); -#endif -#ifndef QT_NO_TEXTODFWRITER - { - QBuffer buffer; - QTextDocumentWriter writer(&buffer, "ODF"); - writer.write(fragment); - buffer.close(); - that->setData(QLatin1String("application/vnd.oasis.opendocument.text"), buffer.data()); - } -#endif - that->setText(fragment.toPlainText()); - fragment = QTextDocumentFragment(); -} - -QT_END_NAMESPACE - -#include "moc_qtextcontrol_p.cpp" - -#endif // QT_NO_TEXTCONTROL |