--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbcore/primitives/hbrichtextitem.cpp Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,533 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (developer.feedback@nokia.com)
+**
+** This file is part of the HbCore module of the UI Extensions for Mobile.
+**
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at developer.feedback@nokia.com.
+**
+****************************************************************************/
+
+#include "hbrichtextitem.h"
+#include "hbrichtextitem_p.h"
+#include "hbtextutils_p.h"
+#include "hbcolorscheme.h"
+#include "hbevent.h"
+
+#include <QTextDocument>
+#include <QStyle>
+#include <QGraphicsSceneResizeEvent>
+#include <QTextBlock>
+#include <QTextLayout>
+#include <QPainter>
+#include <QAbstractTextDocumentLayout>
+
+const int KMinimumLetersToShow = 4;
+
+static const QString KDefaultColorThemeName = "qtc_view_normal";
+
+HbRichTextItemPrivate::HbRichTextItemPrivate() :
+ mAlignment(Qt::AlignLeft|Qt::AlignVCenter),
+ mTextOption(mAlignment),
+ mDontPrint(false),
+ mDontClip(false),
+ mRtf(0)
+{
+}
+
+HbRichTextItemPrivate::~HbRichTextItemPrivate()
+{
+}
+
+/*
+ * private constructor
+ */
+void HbRichTextItemPrivate::init()
+{
+ Q_Q(HbRichTextItem);
+
+ q->setFlag(QGraphicsItem::ItemClipsToShape, !mDontClip);
+ q->setFlag(QGraphicsItem::ItemIsSelectable, false);
+ q->setFlag(QGraphicsItem::ItemIsFocusable, false);
+
+ mRtf = new QTextDocument(q);
+ mRtf->setDocumentMargin(0.0); // no margins needed
+
+ mTextOption.setWrapMode(QTextOption::NoWrap);
+ mRtf->setDefaultTextOption(mTextOption);
+
+ mRtf->setDefaultFont(q->font());
+}
+
+void HbRichTextItemPrivate::clear()
+{
+ delete mRtf;
+}
+
+int HbRichTextItemPrivate::textFlagsFromTextOption() const
+{
+ int flags = (int)mAlignment;
+
+ switch(mTextOption.wrapMode()) {
+ case QTextOption::NoWrap:
+ flags |= Qt::TextSingleLine;
+ break;
+ case QTextOption::WordWrap:
+ flags |=Qt::TextWordWrap;
+ break;
+ case QTextOption::ManualWrap:
+ break;
+ case QTextOption::WrapAnywhere:
+ flags |=Qt::TextWrapAnywhere;
+ break;
+ case QTextOption::WrapAtWordBoundaryOrAnywhere:
+ flags |=Qt::TextWordWrap | Qt::TextWrapAnywhere;
+ break;
+ }
+
+ if(mDontClip) flags |= Qt::TextDontClip;
+ if(mDontPrint) flags |= Qt::TextDontPrint;
+
+ return flags;
+}
+
+bool HbRichTextItemPrivate::setLayoutDirection(Qt::LayoutDirection newDirection)
+{
+ Qt::Alignment oldAlign = mTextOption.alignment();
+ Qt::Alignment alignment = QStyle::visualAlignment(newDirection, mAlignment);
+ if(alignment!=oldAlign) {
+ mTextOption.setAlignment(alignment);
+ mRtf->setDefaultTextOption(mTextOption);
+ return true;
+ }
+ return false;
+}
+
+void HbRichTextItemPrivate::setSize(const QSizeF &newSize)
+{
+ if(mRtf->size()!=newSize) {
+ Q_Q(HbRichTextItem);
+ mRtf->setTextWidth(newSize.width());
+ calculateOffset();
+ q->update();
+ }
+}
+
+// #define HB_RICH_TEXT_ITEM_ALWAS_SHOW_FIRST_LINE
+void HbRichTextItemPrivate::calculateOffset()
+{
+ Q_Q(HbRichTextItem);
+
+ qreal diff;
+ if(mAlignment.testFlag(Qt::AlignTop)) {
+ diff = 0.0;
+ } else {
+ diff = q->geometry().height() - mRtf->size().height();
+ if(!mAlignment.testFlag(Qt::AlignBottom)) {
+ // default align Qt::AlignVCenter if no flags are set
+ diff*=0.5;
+ }
+ }
+#ifdef HB_RICH_TEXT_ITEM_ALWAS_SHOW_FIRST_LINE
+ diff = qMax(diff, (qreal)0.0);
+#endif
+
+ if(diff!=mOffset.y()) {
+ mOffset.setY(diff);
+ q->prepareGeometryChange();
+ }
+}
+
+/*!
+ @proto
+ @hbcore
+ \class HbRichTextItem
+ \brief HbRichTextItem is a item for showing formatted text.
+
+
+ This is mainly used as a primitive in widgets.
+ It derives from HbWidgetBase so it can be layouted.
+
+ */
+
+/*!
+ Constructor for the class.
+ */
+
+HbRichTextItem::HbRichTextItem(QGraphicsItem *parent) :
+ HbWidgetBase(*new HbRichTextItemPrivate, parent)
+{
+ Q_D(HbRichTextItem);
+ d->init();
+}
+
+/*!
+ Constructor which set content using \a html format.
+ */
+HbRichTextItem::HbRichTextItem(const QString &html, QGraphicsItem *parent) :
+ HbWidgetBase(*new HbRichTextItemPrivate, parent)
+{
+ Q_D(HbRichTextItem);
+ d->init();
+ setText(html);
+}
+
+/*
+ Constructor for internal use only
+ */
+HbRichTextItem::HbRichTextItem(HbRichTextItemPrivate &dd, QGraphicsItem *parent) :
+ HbWidgetBase(dd, parent)
+{
+ Q_D(HbRichTextItem);
+ d->init();
+}
+
+/*!
+ Destructor for the class.
+ */
+HbRichTextItem::~HbRichTextItem()
+{
+ Q_D(HbRichTextItem);
+ d->clear();
+}
+
+/*!
+ Sets the \a text in html format.
+
+ \sa HbRichTextItem::text()
+ */
+void HbRichTextItem::setText(const QString &text)
+{
+ Q_D(HbRichTextItem);
+ if (d->mText != text) {
+ d->mText = text;
+ d->mRtf->setHtml(text);
+ updateGeometry();
+ }
+}
+
+/*!
+ Returns the text in html format.
+
+ \sa HbRichTextItem::setText()
+ */
+
+QString HbRichTextItem::text() const
+{
+ Q_D( const HbRichTextItem );
+ return d->mText;
+}
+
+/*!
+ Sets \a alignment for the text from Qt::Alignment enumeration.
+
+ \sa HbRichTextItem::alignment()
+ */
+void HbRichTextItem::setAlignment(Qt::Alignment alignment)
+{
+ Q_D( HbRichTextItem );
+ d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextAlign, true);
+ alignment &= Qt::AlignVertical_Mask | Qt::AlignHorizontal_Mask;
+ if( d->mAlignment!=alignment ) {
+ prepareGeometryChange();
+ d->mAlignment = alignment;
+ d->calculateOffset();
+ if(d->setLayoutDirection(layoutDirection())) {
+ update();
+ }
+ }
+}
+
+/*!
+ Returns alignment for the text from Qt::Alignment enumeration.
+
+ \sa HbRichTextItem::setAlignment()
+ */
+Qt::Alignment HbRichTextItem::alignment() const
+{
+ Q_D( const HbRichTextItem );
+ return d->mAlignment;
+}
+
+/*!
+ \reimp
+ */
+void HbRichTextItem::paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *option,
+ QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ Q_D(HbRichTextItem);
+
+ if(!d->mDontPrint) {
+ if(!d->mDontClip) {
+ painter->setClipRect(contentsRect(), Qt::IntersectClip);
+ }
+ painter->translate(d->mOffset);
+ QAbstractTextDocumentLayout::PaintContext context;
+ context.palette.setColor(QPalette::Text, textDefaultColor());
+ d->mRtf->documentLayout()->draw(painter, context);
+ }
+}
+
+/*!
+ \reimp
+
+ Sets new position and relayouts text according to new size.
+ */
+void HbRichTextItem::setGeometry(const QRectF & rect)
+{
+ Q_D(HbRichTextItem);
+
+ HbWidgetBase::setGeometry(rect);
+
+ if(rect.isValid()) {
+ d->setSize(rect.size());
+ }
+}
+
+/*!
+ \reimp
+ */
+QRectF HbRichTextItem::boundingRect () const
+{
+ Q_D(const HbRichTextItem);
+
+ QRectF result(d->mOffset, d->mRtf->size());
+
+ if(!d->mDontClip) {
+ // clip
+ result = result.intersect(QRectF(QPointF(),
+ size()));
+ }
+ return result;
+}
+
+/*!
+ \reimp
+ Relayouts text according to new size.
+ */
+void HbRichTextItem::resizeEvent(QGraphicsSceneResizeEvent *event)
+{
+ Q_D(HbRichTextItem);
+
+ d->setSize(event->newSize());
+}
+
+/*!
+ \reimp
+ This impelementation detects layout direction changes, font changes and theme changes.
+ */
+void HbRichTextItem::changeEvent(QEvent *event)
+{
+ Q_D(HbRichTextItem);
+
+ switch(event->type()) {
+ case QEvent::LayoutDirectionChange: {
+ prepareGeometryChange();
+ if(d->setLayoutDirection(layoutDirection())) {
+ update();
+ }
+ }
+ break;
+
+ case QEvent::FontChange: {
+ d->mRtf->setDefaultFont(font());
+ updateGeometry();
+ }
+ break;
+
+ default:
+ // Listens theme changed event so that item size hint is
+ // update when physical font is changed.
+ if (event->type() == HbEvent::ThemeChanged) {
+ Q_D(HbRichTextItem);
+ d->mDefaultColor = QColor();
+ if(!d->mColor.isValid()) {
+ update();
+ }
+ }
+ }
+ HbWidgetBase::changeEvent(event);
+}
+
+/*!
+ \reimp
+ For which = PreferredSize returns reasonable size (QTextDocument::adjustSize()).
+ For which = MinimumSize returns size of 4 first letters
+ \a constraint width is taken into account.
+ */
+QSizeF HbRichTextItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_D(const HbRichTextItem);
+ QSizeF result;
+ switch(which) {
+ case Qt::MinimumSize: {
+ QTextBlock textBlock = d->mRtf->begin();
+ if(textBlock.isValid() && textBlock.layout()->lineCount() > 0) {
+ QTextLine line = textBlock.layout()->lineAt(0);
+ result.setHeight(line.height());
+ int cursorPos(KMinimumLetersToShow);
+ result.setWidth( line.cursorToX(&cursorPos) );
+
+ qreal doubleDocMargin = d->mRtf->documentMargin() * (qreal)2.0;
+ result.rheight() += doubleDocMargin;
+ result.rwidth() += doubleDocMargin;
+ } else {
+ result = HbWidgetBase::sizeHint(which, constraint);
+ }
+ }
+ break;
+
+ case Qt::PreferredSize: {
+ if(constraint.width()<=0) {
+ d->mRtf->adjustSize();
+ } else {
+ d->mRtf->setTextWidth(constraint.width());
+ }
+ result = d->mRtf->size();
+ }
+ break;
+
+ default:
+ result = HbWidgetBase::sizeHint(which, constraint);
+ }
+ return result;
+}
+
+/*!
+ * @proto
+ * Sets the text wrapping mode.
+ *
+ * \sa HbRichTextItem::textWrapping
+ * \sa QTextOption::setWrapMode
+ */
+void HbRichTextItem::setTextWrapping(Hb::TextWrapping mode)
+{
+ Q_D(HbRichTextItem);
+ d->setApiProtectionFlag(HbWidgetBasePrivate::AC_TextWrapMode, true);
+ QTextOption::WrapMode textWrapMode = static_cast<QTextOption::WrapMode>(mode);
+
+ if(d->mTextOption.wrapMode()!=textWrapMode) {
+ prepareGeometryChange();
+ d->mTextOption.setWrapMode(textWrapMode);
+ d->mRtf->setDefaultTextOption(d->mTextOption);
+ updateGeometry();
+ }
+}
+
+/*!
+ * @proto
+ * Returns style of text wrapping.
+ *
+ * \sa HbRichTextItem::setTextWrapping
+ * \sa QTextOption::wrapMode
+ */
+Hb::TextWrapping HbRichTextItem::textWrapping() const
+{
+ Q_D(const HbRichTextItem);
+
+ return static_cast<Hb::TextWrapping>(d->mTextOption.wrapMode());
+}
+
+/*!
+ * Returns color used as a default text color.
+ * If invalid color was set color for text is fetch from parent widget.
+ * If invalid color was set and no parent widget was set this will return
+ * default foreground color.
+ *
+ * \sa setTextDefaultColor()
+ */
+QColor HbRichTextItem::textDefaultColor() const
+{
+ Q_D( const HbRichTextItem );
+
+ if (d->mColor.isValid()) { // Means user has set text color
+ return d->mColor;
+ }
+ if (!d->mDefaultColor.isValid()) {
+ d->mDefaultColor = HbColorScheme::color(KDefaultColorThemeName);
+ }
+
+ return d->mDefaultColor;
+}
+
+/*!
+ * Sets color of text.
+ * If invalid color was set color for text is fetch from parent widget.
+ * If invalid color was set and no parent widget was set default foreground color
+ * will be used
+ *
+ * \sa textDefaultColor()
+ */
+void HbRichTextItem::setTextDefaultColor(const QColor &color)
+{
+ Q_D(HbRichTextItem);
+ if (d->mColor != color) {
+ d->mColor = color;
+ update();
+ }
+}
+
+/*!
+ * Shows (default) or hides text. Size hint remains unchanged (same as when text is visible).
+ */
+void HbRichTextItem::setTextVisible(bool isVisible)
+{
+ Q_D(HbRichTextItem);
+ if( d->mDontPrint == isVisible ) {
+ d->mDontPrint = !isVisible;
+ update();
+ }
+}
+
+/*!
+ * Returns if text is visible.
+ */
+bool HbRichTextItem::isTextVisible() const
+{
+ Q_D(const HbRichTextItem);
+ return !d->mDontPrint;
+}
+
+/*!
+ * Enables (default) or disables text clipping when item geometry is too small.
+ */
+void HbRichTextItem::setTextClip(bool cliping)
+{
+ Q_D(HbRichTextItem);
+ if( d->mDontClip == cliping ) {
+ prepareGeometryChange();
+ d->mDontClip = !cliping;
+ setFlag(QGraphicsItem::ItemClipsToShape, cliping);
+ update();
+ }
+}
+
+/*!
+ * Returns true if text is clipped when item geometry is too small.
+ */
+bool HbRichTextItem::isTextClip() const
+{
+ Q_D(const HbRichTextItem);
+ return !d->mDontClip;
+}
+
+// end of file