From e9a25332df933227c6b71a1654260d8421f56415 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 26 May 2010 15:15:45 +1000 Subject: Fix TextEdit clipping when not wrapped. Rename most-useful-wrap-mode to "Wrap". --- .../twitter/TwitterCore/HomeTitleBar.qml | 2 +- doc/src/snippets/declarative/texteditor.qml | 8 ++-- .../graphicsitems/qdeclarativepainteditem.cpp | 17 ++++++-- .../graphicsitems/qdeclarativepainteditem_p.h | 1 + src/declarative/graphicsitems/qdeclarativetext.cpp | 37 ++++++++++++++---- src/declarative/graphicsitems/qdeclarativetext_p.h | 9 ++++- .../graphicsitems/qdeclarativetextedit.cpp | 45 +++++++++++++++++----- .../graphicsitems/qdeclarativetextedit_p.h | 9 ++++- .../qmlvisual/qdeclarativetext/font/plaintext.qml | 2 +- .../qmlvisual/qdeclarativetext/font/richtext.qml | 2 +- .../qmlvisual/qdeclarativetextedit/wrap.qml | 2 +- 11 files changed, 104 insertions(+), 30 deletions(-) diff --git a/demos/declarative/twitter/TwitterCore/HomeTitleBar.qml b/demos/declarative/twitter/TwitterCore/HomeTitleBar.qml index 2eaa40c..3828a40 100644 --- a/demos/declarative/twitter/TwitterCore/HomeTitleBar.qml +++ b/demos/declarative/twitter/TwitterCore/HomeTitleBar.qml @@ -129,7 +129,7 @@ Item { width: parent.width - 12 height: parent.height - 8 font.pointSize: 10 - wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere + wrapMode: TextEdit.Wrap color: "#151515"; selectionColor: "green" } Keys.forwardTo: [(returnKey), (editor)] diff --git a/doc/src/snippets/declarative/texteditor.qml b/doc/src/snippets/declarative/texteditor.qml index 0bd79b5..6735c6c 100644 --- a/doc/src/snippets/declarative/texteditor.qml +++ b/doc/src/snippets/declarative/texteditor.qml @@ -45,7 +45,8 @@ Flickable { id: flick width: 300; height: 200; - contentHeight: edit.height + contentWidth: edit.paintedWidth + contentHeight: edit.paintedHeight clip: true function ensureVisible(r) @@ -62,9 +63,10 @@ Flickable { TextEdit { id: edit - width: parent.width + width: flick.width + height: flick.height focus: true - wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere + wrapMode: TextEdit.Wrap onCursorRectangleChanged: flick.ensureVisible(cursorRectangle) } } diff --git a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp index c4f0b86..13d1b61 100644 --- a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp +++ b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp @@ -152,8 +152,6 @@ void QDeclarativePaintedItem::setContentsSize(const QSize &size) Q_D(QDeclarativePaintedItem); if (d->contentsSize == size) return; d->contentsSize = size; - setImplicitWidth(size.width()*d->contentsScale); - setImplicitHeight(size.height()*d->contentsScale); clearCache(); update(); emit contentsSizeChanged(); @@ -170,8 +168,6 @@ void QDeclarativePaintedItem::setContentsScale(qreal scale) Q_D(QDeclarativePaintedItem); if (d->contentsScale == scale) return; d->contentsScale = scale; - setImplicitWidth(d->contentsSize.width()*scale); - setImplicitHeight(d->contentsSize.height()*scale); clearCache(); update(); emit contentsScaleChanged(); @@ -232,6 +228,19 @@ void QDeclarativePaintedItem::setCacheFrozen(bool frozen) // XXX clear cache? } +QRectF QDeclarativePaintedItem::boundingRect() const +{ + Q_D(const QDeclarativePaintedItem); + qreal w = d->mWidth; + QSizeF sz = d->contentsSize * d->contentsScale; + if (w < sz.width()) + w = sz.width(); + qreal h = d->mHeight; + if (h < sz.height()) + h = sz.height(); + return QRectF(0.0,0.0,w,h); +} + /*! \internal */ diff --git a/src/declarative/graphicsitems/qdeclarativepainteditem_p.h b/src/declarative/graphicsitems/qdeclarativepainteditem_p.h index 8d08ba2..86f065a 100644 --- a/src/declarative/graphicsitems/qdeclarativepainteditem_p.h +++ b/src/declarative/graphicsitems/qdeclarativepainteditem_p.h @@ -93,6 +93,7 @@ protected: const QVariant &value); void setCacheFrozen(bool); + QRectF boundingRect() const; Q_SIGNALS: void fillColorChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 4e7e0fd..2c1eb67 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -499,13 +499,10 @@ void QDeclarativeText::setVAlign(VAlignment align) wrap if an explicit width has been set. wrapMode can be one of: \list - \o Text.NoWrap - no wrapping will be performed. - \o Text.WordWrap - wrapping is done on word boundaries. If the text cannot be - word-wrapped to the specified width it will be partially drawn outside of the item's bounds. - If this is undesirable then enable clipping on the item (Item::clip). - \o Text.WrapAnywhere - Text can be wrapped at any point on a line, even if it occurs in the middle of a word. - \o Text.WrapAtWordBoundaryOrAnywhere - If possible, wrapping occurs at a word boundary; otherwise it - will occur at the appropriate point on the line, even in the middle of a word. + \o Text.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width. + \o Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width. + \o Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. + \o Text.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. \endlist The default is Text.NoWrap. @@ -715,6 +712,7 @@ void QDeclarativeTextPrivate::updateSize() QFontMetrics fm(font); if (text.isEmpty()) { q->setImplicitHeight(fm.height()); + emit q->paintedSizeChanged(); return; } @@ -753,11 +751,36 @@ void QDeclarativeTextPrivate::updateSize() //### need to comfirm cost of always setting these for richText q->setImplicitWidth(richText ? (int)doc->idealWidth() : size.width()); q->setImplicitHeight(richText ? (int)doc->size().height() : size.height()); + emit q->paintedSizeChanged(); } else { dirty = true; } } +/*! + \qmlproperty real Text::paintedWidth + + Returns the width of the text, including width past the width + which is covered due to insufficient wrapping if WrapMode is set. +*/ +qreal QDeclarativeText::paintedWidth() const +{ + return implicitWidth(); +} + +/*! + \qmlproperty real Text::paintedHeight + + Returns the height of the text, including height past the height + which is covered due to there being more text than fits in the set height. +*/ +qreal QDeclarativeText::paintedHeight() const +{ + return implicitHeight(); +} + + + // ### text layout handling should be profiled and optimized as needed // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine); diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index 00ce126..db21140 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -71,6 +71,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeText : public QDeclarativeItem Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode? + Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) + Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) public: QDeclarativeText(QDeclarativeItem *parent=0); @@ -98,7 +100,8 @@ public: enum WrapMode { NoWrap = QTextOption::NoWrap, WordWrap = QTextOption::WordWrap, WrapAnywhere = QTextOption::WrapAnywhere, - WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere + WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT + Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; QString text() const; @@ -137,6 +140,9 @@ public: int resourcesLoading() const; // mainly for testing + qreal paintedWidth() const; + qreal paintedHeight() const; + Q_SIGNALS: void textChanged(const QString &text); void linkActivated(const QString &link); @@ -149,6 +155,7 @@ Q_SIGNALS: void wrapModeChanged(); void textFormatChanged(TextFormat textFormat); void elideModeChanged(TextElideMode mode); + void paintedSizeChanged(); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index a154d53..f105171 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -484,14 +484,13 @@ void QDeclarativeTextEdit::setVAlign(QDeclarativeTextEdit::VAlignment alignment) The text will only wrap if an explicit width has been set. \list - \o TextEdit.NoWrap - no wrapping will be performed. - \o TextEdit.WordWrap - wrapping is done on word boundaries. - \o TextEdit.WrapAnywhere - Text can be wrapped at any point on a line, even if it occurs in the middle of a word. - \o TextEdit.WrapAtWordBoundaryOrAnywhere - If possible, wrapping occurs at a word boundary; otherwise it - will occur at the appropriate point on the line, even in the middle of a word. + \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width. + \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width. + \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. + \o TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. \endlist - The default is TextEdit.NoWrap. + The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap. */ QDeclarativeTextEdit::WrapMode QDeclarativeTextEdit::wrapMode() const { @@ -511,6 +510,29 @@ void QDeclarativeTextEdit::setWrapMode(WrapMode mode) } /*! + \qmlproperty real TextEdit::paintedWidth + + Returns the width of the text, including width past the width + which is covered due to insufficient wrapping if WrapMode is set. +*/ +qreal QDeclarativeTextEdit::paintedWidth() const +{ + return implicitWidth(); +} + +/*! + \qmlproperty real TextEdit::paintedHeight + + Returns the height of the text, including height past the height + which is covered due to there being more text than fits in the set height. +*/ +qreal QDeclarativeTextEdit::paintedHeight() const +{ + return implicitHeight(); +} + + +/*! \qmlproperty bool TextEdit::cursorVisible If true the text edit shows a cursor. @@ -1156,7 +1178,7 @@ void QDeclarativeTextEdit::updateSize() int dy = height(); // ### assumes that if the width is set, the text will fill to edges // ### (unless wrap is false, then clipping will occur) - if (widthValid()) + if (widthValid() && d->document->textWidth() != width()) d->document->setTextWidth(width()); dy -= (int)d->document->size().height(); @@ -1172,7 +1194,7 @@ void QDeclarativeTextEdit::updateSize() //### need to comfirm cost of always setting these int newWidth = qCeil(d->document->idealWidth()); - if (!widthValid()) + if (!widthValid() && d->document->textWidth() != newWidth) d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug) int cursorWidth = 1; if(d->cursor) @@ -1182,9 +1204,12 @@ void QDeclarativeTextEdit::updateSize() newWidth += 3;// ### Need a better way of accounting for space between char and cursor // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed. setImplicitWidth(newWidth); - setImplicitHeight(d->document->isEmpty() ? fm.height() : (int)d->document->size().height()); + qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height(); + setImplicitHeight(newHeight); + + setContentsSize(QSize(newWidth, newHeight)); - setContentsSize(QSize(width(), height())); + emit paintedSizeChanged(); } else { d->dirty = true; } diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 891b868..51bb974 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -74,6 +74,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) + Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) + Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged) Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged) @@ -113,7 +115,8 @@ public: enum WrapMode { NoWrap = QTextOption::NoWrap, WordWrap = QTextOption::WordWrap, WrapAnywhere = QTextOption::WrapAnywhere, - WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere + WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT + Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; QString text() const; @@ -185,8 +188,12 @@ public: QVariant inputMethodQuery(Qt::InputMethodQuery property) const; + qreal paintedWidth() const; + qreal paintedHeight() const; + Q_SIGNALS: void textChanged(const QString &); + void paintedSizeChanged(); void cursorPositionChanged(); void cursorRectangleChanged(); void selectionStartChanged(); diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/font/plaintext.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/font/plaintext.qml index d948e4a..73dd4d7 100644 --- a/tests/auto/declarative/qmlvisual/qdeclarativetext/font/plaintext.qml +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/font/plaintext.qml @@ -85,7 +85,7 @@ Rectangle { text: s.text + " thisisaverylongstringwithnospaces"; width: 150; wrapMode: Text.WrapAnywhere } Text { - text: s.text + " thisisaverylongstringwithnospaces"; width: 150; wrapMode: Text.WrapAtWordBoundaryOrAnywhere + text: s.text + " thisisaverylongstringwithnospaces"; width: 150; wrapMode: Text.Wrap } } } diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/font/richtext.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/font/richtext.qml index d10cfd3..b41b93a 100644 --- a/tests/auto/declarative/qmlvisual/qdeclarativetext/font/richtext.qml +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/font/richtext.qml @@ -85,7 +85,7 @@ Rectangle { text: s.text + " thisisaverylongstringwithnospaces"; width: 150; wrapMode: Text.WrapAnywhere } Text { - text: s.text + " thisisaverylongstringwithnospaces"; width: 150; wrapMode: Text.WrapAtWordBoundaryOrAnywhere + text: s.text + " thisisaverylongstringwithnospaces"; width: 150; wrapMode: Text.Wrap } } } diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/wrap.qml index abb4464..a1dc5bf 100644 --- a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/wrap.qml +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/wrap.qml @@ -27,7 +27,7 @@ Item { TextEdit { width: 150 height: 100 - wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere + wrapMode: TextEdit.Wrap text: "This is a test that text edit wraps correctly. thisisaverylongstringwithnospaces" y:300 } -- cgit v0.12