src/qt3support/text/q3simplerichtext.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt3Support module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "q3simplerichtext.h"
       
    43 
       
    44 #ifndef QT_NO_RICHTEXT
       
    45 #include "q3richtext_p.h"
       
    46 #include "qapplication.h"
       
    47 
       
    48 QT_BEGIN_NAMESPACE
       
    49 
       
    50 class Q3SimpleRichTextData
       
    51 {
       
    52 public:
       
    53     Q3TextDocument *doc;
       
    54     QFont font;
       
    55     int cachedWidth;
       
    56     bool cachedWidthWithPainter;
       
    57     void adjustSize();
       
    58 };
       
    59 
       
    60 // Pull this private function in from qglobal.cpp
       
    61 Q_CORE_EXPORT unsigned int qt_int_sqrt(unsigned int n);
       
    62 
       
    63 void Q3SimpleRichTextData::adjustSize() {
       
    64     QFontMetrics fm(font);
       
    65     int mw =  fm.width(QString(QLatin1Char('x'))) * 80;
       
    66     int w = mw;
       
    67     doc->doLayout(0,w);
       
    68     if (doc->widthUsed() != 0) {
       
    69         w = qt_int_sqrt(5 * doc->height() * doc->widthUsed() / 3);
       
    70         doc->doLayout(0, qMin(w, mw));
       
    71 
       
    72         if (w*3 < 5*doc->height()) {
       
    73             w = qt_int_sqrt(2 * doc->height() * doc->widthUsed());
       
    74             doc->doLayout(0,qMin(w, mw));
       
    75         }
       
    76     }
       
    77     cachedWidth = doc->width();
       
    78     cachedWidthWithPainter = false;
       
    79 }
       
    80 
       
    81 /*!
       
    82     \class Q3SimpleRichText
       
    83     \brief The Q3SimpleRichText class provides a small displayable piece of rich text.
       
    84 
       
    85     \compat
       
    86 
       
    87     This class encapsulates simple rich text usage in which a string
       
    88     is interpreted as rich text and can be drawn. This is particularly
       
    89     useful if you want to display some rich text in a custom widget. A
       
    90     Q3StyleSheet is needed to interpret the tags and format the rich
       
    91     text. Qt provides a default HTML-like style sheet, but you may
       
    92     define custom style sheets.
       
    93 
       
    94     Once created, the rich text object can be queried for its width(),
       
    95     height(), and the actual width used (see widthUsed()). Most
       
    96     importantly, it can be drawn on any given QPainter with draw().
       
    97     Q3SimpleRichText can also be used to implement hypertext or active
       
    98     text facilities by using anchorAt(). A hit test through inText()
       
    99     makes it possible to use simple rich text for text objects in
       
   100     editable drawing canvases.
       
   101 
       
   102     Once constructed from a string the contents cannot be changed,
       
   103     only resized. If the contents change, just throw the rich text
       
   104     object away and make a new one with the new contents.
       
   105 
       
   106     For large documents use QTextEdit or QTextBrowser. For very small
       
   107     items of rich text you can use a QLabel.
       
   108 
       
   109     If you are using Q3SimpleRichText to print in high resolution you
       
   110     should call setWidth(QPainter, int) so that the content will be
       
   111     laid out properly on the page.
       
   112 */
       
   113 
       
   114 /*!
       
   115     Constructs a Q3SimpleRichText from the rich text string \a text and
       
   116     the font \a fnt.
       
   117 
       
   118     The font is used as a basis for the text rendering. When using
       
   119     rich text rendering on a widget \e w, you would normally specify
       
   120     the widget's font, for example:
       
   121 
       
   122     \snippet doc/src/snippets/code/src_qt3support_text_q3simplerichtext.cpp 0
       
   123 
       
   124     \a context is the optional context of the rich text object. This
       
   125     becomes important if \a text contains relative references, for
       
   126     example within image tags. Q3SimpleRichText always uses the default
       
   127     mime source factory (see \l{Q3MimeSourceFactory::defaultFactory()})
       
   128     to resolve those references. The context will then be used to
       
   129     calculate the absolute path. See
       
   130     Q3MimeSourceFactory::makeAbsolute() for details.
       
   131 
       
   132     The \a sheet is an optional style sheet. If it is 0, the default
       
   133     style sheet will be used (see \l{Q3StyleSheet::defaultSheet()}).
       
   134 */
       
   135 
       
   136 Q3SimpleRichText::Q3SimpleRichText(const QString& text, const QFont& fnt,
       
   137                                   const QString& context, const Q3StyleSheet* sheet)
       
   138 {
       
   139     d = new Q3SimpleRichTextData;
       
   140     d->cachedWidth = -1;
       
   141     d->cachedWidthWithPainter = false;
       
   142     d->font = fnt;
       
   143     d->doc = new Q3TextDocument(0);
       
   144     d->doc->setTextFormat(Qt::RichText);
       
   145     d->doc->setLeftMargin(0);
       
   146     d->doc->setRightMargin(0);
       
   147     d->doc->setFormatter(new Q3TextFormatterBreakWords);
       
   148     d->doc->setStyleSheet((Q3StyleSheet*)sheet);
       
   149     d->doc->setDefaultFormat(fnt, QColor());
       
   150     d->doc->setText(text, context);
       
   151 }
       
   152 
       
   153 
       
   154 /*!
       
   155     Constructs a Q3SimpleRichText from the rich text string \a text and
       
   156     the font \a fnt.
       
   157 
       
   158     This is a slightly more complex constructor for Q3SimpleRichText
       
   159     that takes an additional mime source factory \a factory, a page
       
   160     break parameter \a pageBreak and a bool \a linkUnderline. \a
       
   161     linkColor is only provided for compatibility, but has no effect,
       
   162     as QPalette::link() color is used now.
       
   163 
       
   164     \a context is the optional context of the rich text object. This
       
   165     becomes important if \a text contains relative references, for
       
   166     example within image tags. Q3SimpleRichText always uses the default
       
   167     mime source factory (see \l{Q3MimeSourceFactory::defaultFactory()})
       
   168     to resolve those references. The context will then be used to
       
   169     calculate the absolute path. See
       
   170     Q3MimeSourceFactory::makeAbsolute() for details.
       
   171 
       
   172     The \a sheet is an optional style sheet. If it is 0, the default
       
   173     style sheet will be used (see \l{Q3StyleSheet::defaultSheet()}).
       
   174 
       
   175     This constructor is useful for creating a Q3SimpleRichText object
       
   176     suitable for printing. Set \a pageBreak to be the height of the
       
   177     contents area of the pages.
       
   178 */
       
   179 
       
   180 Q3SimpleRichText::Q3SimpleRichText(const QString& text, const QFont& fnt,
       
   181                                   const QString& context, const Q3StyleSheet* sheet,
       
   182                                   const Q3MimeSourceFactory* factory, int pageBreak,
       
   183                                   const QColor& /*linkColor*/, bool linkUnderline)
       
   184 {
       
   185     d = new Q3SimpleRichTextData;
       
   186     d->cachedWidth = -1;
       
   187     d->cachedWidthWithPainter = false;
       
   188     d->font = fnt;
       
   189     d->doc = new Q3TextDocument(0);
       
   190     d->doc->setTextFormat(Qt::RichText);
       
   191     d->doc->setFormatter(new Q3TextFormatterBreakWords);
       
   192     d->doc->setStyleSheet((Q3StyleSheet*)sheet);
       
   193     d->doc->setDefaultFormat(fnt, QColor());
       
   194     d->doc->flow()->setPageSize(pageBreak);
       
   195     d->doc->setPageBreakEnabled(true);
       
   196 #ifndef QT_NO_MIME
       
   197     d->doc->setMimeSourceFactory((Q3MimeSourceFactory*)factory);
       
   198 #endif
       
   199     d->doc->setUnderlineLinks(linkUnderline);
       
   200     d->doc->setText(text, context);
       
   201 }
       
   202 
       
   203 /*!
       
   204     Destroys the rich text object, freeing memory.
       
   205 */
       
   206 
       
   207 Q3SimpleRichText::~Q3SimpleRichText()
       
   208 {
       
   209     delete d->doc;
       
   210     delete d;
       
   211 }
       
   212 
       
   213 /*!
       
   214     \overload
       
   215 
       
   216     Sets the width of the rich text object to \a w pixels.
       
   217 
       
   218     \sa height(), adjustSize()
       
   219 */
       
   220 
       
   221 void Q3SimpleRichText::setWidth(int w)
       
   222 {
       
   223     if (w == d->cachedWidth && !d->cachedWidthWithPainter)
       
   224         return;
       
   225     d->doc->formatter()->setAllowBreakInWords(d->doc->isPageBreakEnabled());
       
   226     d->cachedWidth = w;
       
   227     d->cachedWidthWithPainter = false;
       
   228     d->doc->doLayout(0, w);
       
   229 }
       
   230 
       
   231 /*!
       
   232     Sets the width of the rich text object to \a w pixels,
       
   233     recalculating the layout as if it were to be drawn with painter \a
       
   234     p.
       
   235 
       
   236     Passing a painter is useful when you intend drawing on devices
       
   237     other than the screen, for example a QPrinter.
       
   238 
       
   239     \sa height(), adjustSize()
       
   240 */
       
   241 
       
   242 void Q3SimpleRichText::setWidth(QPainter *p, int w)
       
   243 {
       
   244     if (w == d->cachedWidth  && d->cachedWidthWithPainter)
       
   245         return;
       
   246     d->doc->formatter()->setAllowBreakInWords(d->doc->isPageBreakEnabled() ||
       
   247                        (p && p->device() &&
       
   248                      p->device()->devType() == QInternal::Printer));
       
   249     p->save();
       
   250     d->cachedWidth = w;
       
   251     d->cachedWidthWithPainter = true;
       
   252     d->doc->doLayout(p, w);
       
   253     p->restore();
       
   254 }
       
   255 
       
   256 /*!
       
   257     Returns the set width of the rich text object in pixels.
       
   258 
       
   259     \sa widthUsed()
       
   260 */
       
   261 
       
   262 int Q3SimpleRichText::width() const
       
   263 {
       
   264     if (d->cachedWidth < 0)
       
   265         d->adjustSize();
       
   266     return d->doc->width();
       
   267 }
       
   268 
       
   269 /*!
       
   270     Returns the width in pixels that is actually used by the rich text
       
   271     object. This can be smaller or wider than the set width.
       
   272 
       
   273     It may be wider, for example, if the text contains images or
       
   274     non-breakable words that are already wider than the available
       
   275     space. It's smaller when the object only consists of lines that do
       
   276     not fill the width completely.
       
   277 
       
   278     \sa width()
       
   279 */
       
   280 
       
   281 int Q3SimpleRichText::widthUsed() const
       
   282 {
       
   283     if (d->cachedWidth < 0)
       
   284         d->adjustSize();
       
   285     return d->doc->widthUsed();
       
   286 }
       
   287 
       
   288 /*!
       
   289     Returns the height of the rich text object in pixels.
       
   290 
       
   291     \sa setWidth()
       
   292 */
       
   293 
       
   294 int Q3SimpleRichText::height() const
       
   295 {
       
   296     if (d->cachedWidth < 0)
       
   297         d->adjustSize();
       
   298     return d->doc->height();
       
   299 }
       
   300 
       
   301 /*!
       
   302     Adjusts the rich text object to a reasonable size.
       
   303 
       
   304     \sa setWidth()
       
   305 */
       
   306 
       
   307 void Q3SimpleRichText::adjustSize()
       
   308 {
       
   309     d->adjustSize();
       
   310 }
       
   311 
       
   312 /*!
       
   313     Draws the formatted text with painter \a p, at position (\a x, \a
       
   314     y), clipped to \a clipRect. The clipping rectangle is given in the
       
   315     rich text object's coordinates translated by (\a x, \a y). Passing
       
   316     an null rectangle results in no clipping. Colors from the color
       
   317     group \a cg are used as needed, and if not 0, *\a{paper} is
       
   318     used as the background brush.
       
   319 
       
   320     Note that the display code is highly optimized to reduce flicker,
       
   321     so passing a brush for \a paper is preferable to simply clearing
       
   322     the area to be painted and then calling this without a brush.
       
   323 */
       
   324 
       
   325 void Q3SimpleRichText::draw(QPainter *p, int x, int y, const QRect& clipRect,
       
   326                             const QColorGroup &cg, const QBrush* paper) const
       
   327 {
       
   328     p->save();
       
   329     if (d->cachedWidth < 0)
       
   330         d->adjustSize();
       
   331     QRect r = clipRect;
       
   332     if (!r.isNull())
       
   333         r.moveBy(-x, -y);
       
   334 
       
   335     if (paper)
       
   336         d->doc->setPaper(new QBrush(*paper));
       
   337     QPalette pal2 = cg;
       
   338     if (d->doc->paper())
       
   339         pal2.setBrush(QPalette::Base, *d->doc->paper());
       
   340 
       
   341     if (!clipRect.isNull())
       
   342         p->setClipRect(clipRect);
       
   343     p->translate(x, y);
       
   344     d->doc->draw(p, r, pal2, paper);
       
   345     p->translate(-x, -y);
       
   346     p->restore();
       
   347 }
       
   348 
       
   349 
       
   350 /*! \fn void Q3SimpleRichText::draw(QPainter *p, int x, int y, const QRegion& clipRegion,
       
   351   const QColorGroup &cg, const QBrush* paper) const
       
   352 
       
   353   Use the version with clipRect instead of this \a clipRegion version,
       
   354   since this region version has problems with larger documents on some
       
   355   platforms (on X11 regions internally are represented with 16-bit
       
   356   coordinates).
       
   357 */
       
   358 
       
   359 
       
   360 
       
   361 /*!
       
   362     Returns the context of the rich text object. If no context has
       
   363     been specified in the constructor, an empty string is returned. The
       
   364     context is the path to use to look up relative links, such as
       
   365     image tags and anchor references.
       
   366 */
       
   367 
       
   368 QString Q3SimpleRichText::context() const
       
   369 {
       
   370     return d->doc->context();
       
   371 }
       
   372 
       
   373 /*!
       
   374     Returns the anchor at the requested position, \a pos. An empty
       
   375     string is returned if no anchor is specified for this position.
       
   376 */
       
   377 
       
   378 QString Q3SimpleRichText::anchorAt(const QPoint& pos) const
       
   379 {
       
   380     if (d->cachedWidth < 0)
       
   381         d->adjustSize();
       
   382     Q3TextCursor c(d->doc);
       
   383     c.place(pos, d->doc->firstParagraph(), true);
       
   384     return c.paragraph()->at(c.index())->anchorHref();
       
   385 }
       
   386 
       
   387 /*!
       
   388     Returns true if \a pos is within a text line of the rich text
       
   389     object; otherwise returns false.
       
   390 */
       
   391 
       
   392 bool Q3SimpleRichText::inText(const QPoint& pos) const
       
   393 {
       
   394     if (d->cachedWidth < 0)
       
   395         d->adjustSize();
       
   396     if (pos.y()  > d->doc->height())
       
   397         return false;
       
   398     Q3TextCursor c(d->doc);
       
   399     c.place(pos, d->doc->firstParagraph());
       
   400     return c.totalOffsetX() + c.paragraph()->at(c.index())->x +
       
   401         c.paragraph()->at(c.index())->format()->width(c.paragraph()->at(c.index())->c) > pos.x();
       
   402 }
       
   403 
       
   404 /*!
       
   405     Sets the default font for the rich text object to \a f
       
   406 */
       
   407 
       
   408 void Q3SimpleRichText::setDefaultFont(const QFont &f)
       
   409 {
       
   410     if (d->font == f)
       
   411         return;
       
   412     d->font = f;
       
   413     d->cachedWidth = -1;
       
   414     d->cachedWidthWithPainter = false;
       
   415     d->doc->setDefaultFormat(f, QColor());
       
   416     d->doc->setText(d->doc->originalText(), d->doc->context());
       
   417 }
       
   418 
       
   419 QT_END_NAMESPACE
       
   420 
       
   421 #endif //QT_NO_RICHTEXT