summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/text/qglyphrun.cpp45
-rw-r--r--src/gui/text/qglyphrun.h3
-rw-r--r--src/gui/text/qglyphrun_p.h2
-rw-r--r--src/gui/text/qtextcontrol.cpp24
-rw-r--r--src/gui/text/qtextcontrol_p.h3
-rw-r--r--src/gui/text/qtextlayout.cpp63
-rw-r--r--src/gui/text/qtextobject.cpp17
-rw-r--r--src/gui/text/qtextobject.h2
-rw-r--r--src/gui/widgets/qlinecontrol.cpp43
-rw-r--r--src/gui/widgets/qlinecontrol_p.h33
10 files changed, 196 insertions, 39 deletions
diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp
index cc825525c4..be9c058693 100644
--- a/src/gui/text/qglyphrun.cpp
+++ b/src/gui/text/qglyphrun.cpp
@@ -45,6 +45,7 @@
#include "qglyphrun.h"
#include "qglyphrun_p.h"
+#include <qdebug.h>
QT_BEGIN_NAMESPACE
@@ -343,12 +344,44 @@ void QGlyphRun::setStrikeOut(bool strikeOut)
}
/*!
- Returns the smallest rectangle that contains all glyphs in this QGlyphRun.
+ Sets the bounding rect of the glyphs in this QGlyphRun to be \a boundingRect. This rectangle
+ will be returned by boundingRect() unless it is empty, in which case the bounding rectangle of the
+ glyphs in the glyph run will be returned instead.
+
+ \note Unless you are implementing text shaping, you should not have to use this function.
+ It is used specifically when the QGlyphRun should represent an area which is smaller than the
+ area of the glyphs it contains. This could happen e.g. if the glyph run is retrieved by calling
+ QTextLayout::glyphRuns() and the specified range only includes part of a ligature (where two or
+ more characters are combined to a single glyph.) When this is the case, the bounding rect should
+ only include the appropriate part of the ligature glyph, based on a calculation of the average
+ width of the characters in the ligature.
+
+ In order to support such a case (an example is selections which should be drawn with a different
+ color than the main text color), it is necessary to clip the painting mechanism to the rectangle
+ returned from boundingRect() to avoid drawing the entire ligature glyph.
+
+ \sa boundingRect()
+
+ \since 5.0
+*/
+void QGlyphRun::setBoundingRect(const QRectF &boundingRect)
+{
+ detach();
+ d->boundingRect = boundingRect;
+}
+
+/*!
+ Returns the smallest rectangle that contains all glyphs in this QGlyphRun. If a bounding rect
+ has been set using setBoundingRect(), then this will be returned. Otherwise the bounding rect
+ will be calculated based on the font metrics of the glyphs in the glyph run.
\since 5.0
*/
QRectF QGlyphRun::boundingRect() const
{
+ if (!d->boundingRect.isEmpty())
+ return d->boundingRect;
+
qreal minX, minY, maxX, maxY;
for (int i=0; i<qMin(d->glyphPositions.size(), d->glyphIndexes.size()); ++i) {
@@ -371,6 +404,16 @@ QRectF QGlyphRun::boundingRect() const
return QRectF(QPointF(minX, minY), QPointF(maxX, maxY));
}
+/*!
+ Returns true if the QGlyphRun does not contain any glyphs.
+
+ \since 5.0
+*/
+bool QGlyphRun::isEmpty() const
+{
+ return d->glyphIndexes.isEmpty();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_RAWFONT
diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h
index b4f02f0d87..da88bc72f9 100644
--- a/src/gui/text/qglyphrun.h
+++ b/src/gui/text/qglyphrun.h
@@ -91,8 +91,11 @@ public:
void setStrikeOut(bool strikeOut);
bool strikeOut() const;
+ void setBoundingRect(const QRectF &boundingRect);
QRectF boundingRect() const;
+ bool isEmpty() const;
+
private:
friend class QGlyphRunPrivate;
friend class QTextLine;
diff --git a/src/gui/text/qglyphrun_p.h b/src/gui/text/qglyphrun_p.h
index a7745e68ce..b632678971 100644
--- a/src/gui/text/qglyphrun_p.h
+++ b/src/gui/text/qglyphrun_p.h
@@ -83,6 +83,7 @@ public:
, glyphIndexes(other.glyphIndexes)
, glyphPositions(other.glyphPositions)
, rawFont(other.rawFont)
+ , boundingRect(other.boundingRect)
, overline(other.overline)
, underline(other.underline)
, strikeOut(other.strikeOut)
@@ -96,6 +97,7 @@ public:
QVector<quint32> glyphIndexes;
QVector<QPointF> glyphPositions;
QRawFont rawFont;
+ QRectF boundingRect;
uint overline : 1;
uint underline : 1;
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 424d1979b2..c29379ed28 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -409,6 +409,8 @@ void QTextControlPrivate::init(Qt::TextFormat format, const QString &text, QText
doc->setUndoRedoEnabled(interactionFlags & Qt::TextEditable);
q->setCursorWidth(-1);
+
+ QObject::connect(q, SIGNAL(updateCursorRequest(QRectF)), q, SIGNAL(updateRequest(QRectF)));
}
void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text, QTextDocument *document)
@@ -547,7 +549,7 @@ void QTextControlPrivate::setCursorPosition(int pos, QTextCursor::MoveMode mode)
void QTextControlPrivate::repaintCursor()
{
Q_Q(QTextControl);
- emit q->updateRequest(cursorRectPlusUnicodeDirectionMarkers(cursor));
+ emit q->updateCursorRequest(cursorRectPlusUnicodeDirectionMarkers(cursor));
}
void QTextControlPrivate::repaintOldAndNewSelection(const QTextCursor &oldSelection)
@@ -565,9 +567,16 @@ void QTextControlPrivate::repaintOldAndNewSelection(const QTextCursor &oldSelect
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));
+ if (!oldSelection.hasSelection() && !cursor.hasSelection()) {
+ if (!oldSelection.isNull())
+ emit q->updateCursorRequest(q->selectionRect(oldSelection) | cursorRectPlusUnicodeDirectionMarkers(oldSelection));
+ emit q->updateCursorRequest(q->selectionRect() | cursorRectPlusUnicodeDirectionMarkers(cursor));
+
+ } else {
+ if (!oldSelection.isNull())
+ emit q->updateRequest(q->selectionRect(oldSelection) | cursorRectPlusUnicodeDirectionMarkers(oldSelection));
+ emit q->updateRequest(q->selectionRect() | cursorRectPlusUnicodeDirectionMarkers(cursor));
+ }
}
}
@@ -2959,6 +2968,12 @@ void QTextControl::setPalette(const QPalette &pal)
d->palette = pal;
}
+bool QTextControl::cursorOn() const
+{
+ Q_D(const QTextControl);
+ return d->cursorOn;
+}
+
QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget *widget) const
{
Q_D(const QTextControl);
@@ -3146,6 +3161,7 @@ void QTextEditMimeData::setup() const
fragment = QTextDocumentFragment();
}
+
QT_END_NAMESPACE
#include "moc_qtextcontrol_p.cpp"
diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h
index cbf26d2122..c5ed0ee1e0 100644
--- a/src/gui/text/qtextcontrol_p.h
+++ b/src/gui/text/qtextcontrol_p.h
@@ -226,6 +226,7 @@ Q_SIGNALS:
void cursorPositionChanged();
// control signals
+ void updateCursorRequest(const QRectF &rect = QRectF());
void updateRequest(const QRectF &rect = QRectF());
void documentSizeChanged(const QSizeF &);
void blockCountChanged(int newBlockCount);
@@ -258,6 +259,8 @@ public:
bool setFocusToNextOrPreviousAnchor(bool next);
bool findNextPrevAnchor(const QTextCursor& from, bool next, QTextCursor& newAnchor);
+ bool cursorOn() const;
+
protected:
virtual void timerEvent(QTimerEvent *e);
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 2535faddc3..8c5e63da54 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -42,6 +42,7 @@
#include "qtextlayout.h"
#include "qtextengine_p.h"
+#include <qthread.h>
#include <qfont.h>
#include <qapplication.h>
#include <qpainter.h>
@@ -2108,8 +2109,10 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q
}
+#if !defined(QT_NO_RAWFONT)
static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &glyphLayout,
- const QPointF &pos, const QTextItem::RenderFlags &flags)
+ const QPointF &pos, const QTextItem::RenderFlags &flags,
+ const QFixed &selectionX, const QFixed &selectionWidth)
{
QGlyphRun glyphRun;
@@ -2117,6 +2120,7 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g
QRawFont font;
QRawFontPrivate *fontD = QRawFontPrivate::get(font);
fontD->fontEngine = fontEngine;
+ fontD->thread = QThread::currentThread();
fontD->fontEngine->ref.ref();
#if defined(Q_WS_WIN)
@@ -2151,13 +2155,27 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g
positionsArray);
Q_ASSERT(glyphsArray.size() == positionsArray.size());
+ qreal fontHeight = font.ascent() + font.descent();
+ qreal minY;
+ qreal maxY;
QVector<quint32> glyphs;
QVector<QPointF> positions;
for (int i=0; i<glyphsArray.size(); ++i) {
glyphs.append(glyphsArray.at(i) & 0xffffff);
- positions.append(positionsArray.at(i).toPointF() + pos);
+
+ QPointF position = positionsArray.at(i).toPointF() + pos;
+ positions.append(position);
+
+ if (i == 0) {
+ maxY = minY = position.y();
+ } else {
+ minY = qMin(minY, position.y());
+ maxY = qMax(maxY, position.y());
+ }
}
+ qreal height = maxY + fontHeight - minY;
+
glyphRun.setGlyphIndexes(glyphs);
glyphRun.setPositions(positions);
@@ -2166,6 +2184,8 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g
glyphRun.setStrikeOut(flags.testFlag(QTextItem::StrikeOut));
glyphRun.setRawFont(font);
+ glyphRun.setBoundingRect(QRectF(selectionX.toReal(), minY, selectionWidth.toReal(), height));
+
return glyphRun;
}
@@ -2182,7 +2202,6 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g
\sa QTextLayout::glyphRuns()
*/
-#if !defined(QT_NO_RAWFONT)
QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
{
const QScriptLine &line = eng->lines[i];
@@ -2196,7 +2215,14 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
if (length < 0)
length = textLength();
- QTextLineItemIterator iterator(eng, i);
+ if (length == 0)
+ return QList<QGlyphRun>();
+
+ QTextLayout::FormatRange selection;
+ selection.start = from;
+ selection.length = length;
+
+ QTextLineItemIterator iterator(eng, i, QPointF(), &selection);
qreal y = line.y.toReal() + line.base().toReal();
QList<QGlyphRun> glyphRuns;
while (!iterator.atEnd()) {
@@ -2206,7 +2232,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
QPointF pos(iterator.x.toReal(), y);
if (from >= 0 && length >= 0 &&
- (from >= si.position + eng->length(&si) || from + length <= si.position)) {
+ (from >= si.position + eng->length(&si)
+ || from + length <= si.position
+ || from + length <= iterator.itemStart
+ || from >= iterator.itemEnd)) {
continue;
}
@@ -2235,19 +2264,22 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
? si.num_glyphs - 1
: logClusters[relativeTo];
+ int itemGlyphsStart = logClusters[iterator.itemStart - si.position];
+ int itemGlyphsEnd = logClusters[iterator.itemEnd - 1 - si.position];
+
QGlyphLayout glyphLayout = eng->shapedGlyphs(&si);
// Calculate new x position of glyph layout for a subset. This becomes somewhat complex
// when we're breaking a RTL script item, since the expected position passed into
// getGlyphPositions() is the left-most edge of the left-most glyph in an RTL run.
if (relativeFrom != (iterator.itemStart - si.position) && !rtl) {
- for (int i=0; i<glyphsStart; ++i) {
+ for (int i=itemGlyphsStart; i<glyphsStart; ++i) {
QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
pos += QPointF((glyphLayout.advances_x[i] + justification).toReal(),
glyphLayout.advances_y[i].toReal());
}
} else if (relativeTo != (iterator.itemEnd - si.position - 1) && rtl) {
- for (int i=glyphLayout.numGlyphs - 1; i>glyphsEnd; --i) {
+ for (int i=itemGlyphsEnd; i>glyphsEnd; --i) {
QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
pos += QPointF((glyphLayout.advances_x[i] + justification).toReal(),
glyphLayout.advances_y[i].toReal());
@@ -2256,6 +2288,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
glyphLayout = glyphLayout.mid(glyphsStart, glyphsEnd - glyphsStart + 1);
+ QFixed x;
+ QFixed width;
+ iterator.getSelectionBounds(&x, &width);
+
if (glyphLayout.numGlyphs > 0) {
QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script);
if (mainFontEngine->type() == QFontEngine::Multi) {
@@ -2270,7 +2306,7 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),
- subLayout, pos, flags));
+ subLayout, pos, flags, x, width));
for (int i = 0; i < subLayout.numGlyphs; i++) {
pos += QPointF(subLayout.advances_x[i].toReal(),
subLayout.advances_y[i].toReal());
@@ -2281,10 +2317,15 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
}
QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
- glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),
- subLayout, pos, flags));
+ QGlyphRun glyphRun = glyphRunWithInfo(multiFontEngine->engine(which),
+ subLayout, pos, flags, x, width);
+ if (!glyphRun.isEmpty())
+ glyphRuns.append(glyphRun);
} else {
- glyphRuns.append(glyphRunWithInfo(mainFontEngine, glyphLayout, pos, flags));
+ QGlyphRun glyphRun = glyphRunWithInfo(mainFontEngine, glyphLayout, pos, flags, x,
+ width);
+ if (!glyphRun.isEmpty())
+ glyphRuns.append(glyphRun);
}
}
}
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index cea5eac465..d641266367 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -1667,21 +1667,24 @@ QTextBlock::iterator &QTextBlock::iterator::operator--()
\sa QGlyphRun, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphRun()
*/
#if !defined(QT_NO_RAWFONT)
-QList<QGlyphRun> QTextFragment::glyphRuns() const
+QList<QGlyphRun> QTextFragment::glyphRuns(int pos, int len) const
{
if (!p || !n)
return QList<QGlyphRun>();
- int pos = position();
- int len = length();
- if (len == 0)
- return QList<QGlyphRun>();
-
- int blockNode = p->blockMap().findNode(pos);
+ int blockNode = p->blockMap().findNode(position());
const QTextBlockData *blockData = p->blockMap().fragment(blockNode);
QTextLayout *layout = blockData->layout;
+ int blockPosition = p->blockMap().position(blockNode);
+ if (pos < 0)
+ pos = position() - blockPosition;
+ if (len < 0)
+ len = length();
+ if (len == 0)
+ return QList<QGlyphRun>();
+
QList<QGlyphRun> ret;
for (int i=0; i<layout->lineCount(); ++i) {
QTextLine textLine = layout->lineAt(i);
diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h
index 9c5cc13539..c2b46e4d12 100644
--- a/src/gui/text/qtextobject.h
+++ b/src/gui/text/qtextobject.h
@@ -317,7 +317,7 @@ public:
QString text() const;
#if !defined(QT_NO_RAWFONT)
- QList<QGlyphRun> glyphRuns() const;
+ QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const;
#endif
private:
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
index 92c84d72e0..9b7d9b83ad 100644
--- a/src/gui/widgets/qlinecontrol.cpp
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -76,6 +76,28 @@ static int qt_passwordEchoDelay = QT_GUI_PASSWORD_ECHO_DELAY;
*/
/*!
+ \internal
+
+ Updates the internal text layout. Returns the ascent of the
+ created QTextLine.
+*/
+int QLineControl::redoTextLayout() const
+{
+ m_textLayout.clearLayout();
+
+ m_textLayout.beginLayout();
+ QTextLine l = m_textLayout.createLine();
+ m_textLayout.endLayout();
+
+#if defined(Q_WS_MAC)
+ if (m_threadChecks)
+ m_textLayoutThread = QThread::currentThread();
+#endif
+
+ return qRound(l.ascent());
+}
+
+/*!
\internal
Updates the display text based of the current edit text
@@ -124,15 +146,12 @@ void QLineControl::updateDisplayText(bool forceUpdate)
m_textLayout.setText(str);
- QTextOption option;
+ QTextOption option = m_textLayout.textOption();
option.setTextDirection(m_layoutDirection);
option.setFlags(QTextOption::IncludeTrailingSpaces);
m_textLayout.setTextOption(option);
- m_textLayout.beginLayout();
- QTextLine l = m_textLayout.createLine();
- m_textLayout.endLayout();
- m_ascent = qRound(l.ascent());
+ m_ascent = redoTextLayout();
if (str != orig || forceUpdate)
emit displayTextChanged(str);
@@ -228,7 +247,7 @@ void QLineControl::del()
if (hasSelectedText()) {
removeSelectedText();
} else {
- int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor;
+ int n = textLayout()->nextCursorPosition(m_cursor) - m_cursor;
while (n--)
internalDelete();
}
@@ -357,7 +376,7 @@ void QLineControl::updatePasswordEchoEditing(bool editing)
*/
int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
{
- return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn);
+ return textLayout()->lineAt(0).xToCursor(x, betweenOrOn);
}
/*!
@@ -368,7 +387,7 @@ int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
*/
QRect QLineControl::cursorRect() const
{
- QTextLine l = m_textLayout.lineAt(0);
+ QTextLine l = textLayout()->lineAt(0);
int c = m_cursor;
if (m_preeditCursor != -1)
c += m_preeditCursor;
@@ -578,14 +597,14 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl
}
if (flags & DrawText)
- m_textLayout.draw(painter, offset, selections, clip);
+ textLayout()->draw(painter, offset, selections, clip);
if (flags & DrawCursor){
int cursor = m_cursor;
if (m_preeditCursor != -1)
cursor += m_preeditCursor;
if (!m_hideCursor && (!m_blinkPeriod || m_blinkStatus))
- m_textLayout.drawCursor(painter, offset, cursor, m_cursorWidth);
+ textLayout()->drawCursor(painter, offset, cursor, m_cursorWidth);
}
}
@@ -601,10 +620,10 @@ void QLineControl::selectWordAtPos(int cursor)
int next = cursor + 1;
if(next > end())
--next;
- int c = m_textLayout.previousCursorPosition(next, QTextLayout::SkipWords);
+ int c = textLayout()->previousCursorPosition(next, QTextLayout::SkipWords);
moveCursor(c, false);
// ## text layout should support end of words.
- int end = m_textLayout.nextCursorPosition(c, QTextLayout::SkipWords);
+ int end = textLayout()->nextCursorPosition(c, QTextLayout::SkipWords);
while (end > cursor && m_text[end-1].isSpace())
--end;
moveCursor(end, true);
diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h
index 44bd7214be..d4c4154b3d 100644
--- a/src/gui/widgets/qlinecontrol_p.h
+++ b/src/gui/widgets/qlinecontrol_p.h
@@ -65,6 +65,7 @@
#include "QtCore/qpoint.h"
#include "QtGui/qcompleter.h"
#include "QtGui/qaccessible.h"
+#include "QtCore/qthread.h"
#include "qplatformdefs.h"
@@ -90,6 +91,10 @@ public:
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
, m_passwordEchoTimer(0)
#endif
+#if defined(Q_WS_MAC)
+ , m_threadChecks(false)
+ , m_textLayoutThread(0)
+ #endif
{
init(txt);
}
@@ -332,11 +337,27 @@ public:
bool processEvent(QEvent *ev);
- QTextLayout *textLayout()
+ QTextLayout *textLayout() const
{
+#if defined(Q_WS_MAC)
+ if (m_threadChecks && QThread::currentThread() != m_textLayoutThread)
+ redoTextLayout();
+#endif
return &m_textLayout;
}
+#if defined(Q_WS_MAC)
+ void setThreadChecks(bool threadChecks)
+ {
+ m_threadChecks = threadChecks;
+ }
+
+ bool threadChecks() const
+ {
+ return m_threadChecks;
+ }
+#endif
+
private:
void init(const QString &txt);
void removeSelectedText();
@@ -433,8 +454,8 @@ private:
QString stripString(const QString &str) const;
int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const;
- // complex text layout
- QTextLayout m_textLayout;
+ // complex text layout (must be mutable so it can be reshaped at will)
+ mutable QTextLayout m_textLayout;
bool m_passwordEchoEditing;
QChar m_passwordCharacter;
@@ -451,6 +472,12 @@ private:
#endif
}
+ int redoTextLayout() const;
+#if defined(Q_WS_MAC)
+ bool m_threadChecks;
+ mutable QThread *m_textLayoutThread;
+#endif
+
Q_SIGNALS:
void cursorPositionChanged(int, int);
void selectionChanged();