1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** All rights reserved.
|
---|
5 | ** Contact: Nokia Corporation ([email protected])
|
---|
6 | **
|
---|
7 | ** This file is part of the QtGui module of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
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 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "qpainter.h"
|
---|
43 | #include "qevent.h"
|
---|
44 | #include "qdrawutil.h"
|
---|
45 | #include "qapplication.h"
|
---|
46 | #include "qabstractbutton.h"
|
---|
47 | #include "qstyle.h"
|
---|
48 | #include "qstyleoption.h"
|
---|
49 | #include <limits.h>
|
---|
50 | #include "qaction.h"
|
---|
51 | #include "qclipboard.h"
|
---|
52 | #include <qdebug.h>
|
---|
53 | #include <qurl.h>
|
---|
54 | #include "qlabel_p.h"
|
---|
55 | #include "private/qstylesheetstyle_p.h"
|
---|
56 | #include <qmath.h>
|
---|
57 |
|
---|
58 | QT_BEGIN_NAMESPACE
|
---|
59 |
|
---|
60 | /*!
|
---|
61 | \class QLabel
|
---|
62 | \brief The QLabel widget provides a text or image display.
|
---|
63 |
|
---|
64 | \ingroup basicwidgets
|
---|
65 |
|
---|
66 | QLabel is used for displaying text or an image. No user
|
---|
67 | interaction functionality is provided. The visual appearance of
|
---|
68 | the label can be configured in various ways, and it can be used
|
---|
69 | for specifying a focus mnemonic key for another widget.
|
---|
70 |
|
---|
71 | A QLabel can contain any of the following content types:
|
---|
72 |
|
---|
73 | \table
|
---|
74 | \header \o Content \o Setting
|
---|
75 | \row \o Plain text
|
---|
76 | \o Pass a QString to setText().
|
---|
77 | \row \o Rich text
|
---|
78 | \o Pass a QString that contains rich text to setText().
|
---|
79 | \row \o A pixmap
|
---|
80 | \o Pass a QPixmap to setPixmap().
|
---|
81 | \row \o A movie
|
---|
82 | \o Pass a QMovie to setMovie().
|
---|
83 | \row \o A number
|
---|
84 | \o Pass an \e int or a \e double to setNum(), which converts
|
---|
85 | the number to plain text.
|
---|
86 | \row \o Nothing
|
---|
87 | \o The same as an empty plain text. This is the default. Set
|
---|
88 | by clear().
|
---|
89 | \endtable
|
---|
90 |
|
---|
91 | When the content is changed using any of these functions, any
|
---|
92 | previous content is cleared.
|
---|
93 |
|
---|
94 | By default, labels display \l{alignment}{left-aligned, vertically-centered}
|
---|
95 | text and images, where any tabs in the text to be displayed are
|
---|
96 | \l{Qt::TextExpandTabs}{automatically expanded}. However, the look
|
---|
97 | of a QLabel can be adjusted and fine-tuned in several ways.
|
---|
98 |
|
---|
99 | The positioning of the content within the QLabel widget area can
|
---|
100 | be tuned with setAlignment() and setIndent(). Text content can
|
---|
101 | also wrap lines along word boundaries with setWordWrap(). For
|
---|
102 | example, this code sets up a sunken panel with a two-line text in
|
---|
103 | the bottom right corner (both lines being flush with the right
|
---|
104 | side of the label):
|
---|
105 |
|
---|
106 | \snippet doc/src/snippets/code/src_gui_widgets_qlabel.cpp 0
|
---|
107 |
|
---|
108 | The properties and functions QLabel inherits from QFrame can also
|
---|
109 | be used to specify the widget frame to be used for any given label.
|
---|
110 |
|
---|
111 | A QLabel is often used as a label for an interactive widget. For
|
---|
112 | this use QLabel provides a useful mechanism for adding an
|
---|
113 | mnemonic (see QKeySequence) that will set the keyboard focus to
|
---|
114 | the other widget (called the QLabel's "buddy"). For example:
|
---|
115 |
|
---|
116 | \snippet doc/src/snippets/code/src_gui_widgets_qlabel.cpp 1
|
---|
117 |
|
---|
118 | In this example, keyboard focus is transferred to the label's
|
---|
119 | buddy (the QLineEdit) when the user presses Alt+P. If the buddy
|
---|
120 | was a button (inheriting from QAbstractButton), triggering the
|
---|
121 | mnemonic would emulate a button click.
|
---|
122 |
|
---|
123 | \table 100%
|
---|
124 | \row
|
---|
125 | \o \inlineimage macintosh-label.png Screenshot of a Macintosh style label
|
---|
126 | \o A label shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
|
---|
127 | \row
|
---|
128 | \o \inlineimage plastique-label.png Screenshot of a Plastique style label
|
---|
129 | \o A label shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
|
---|
130 | \row
|
---|
131 | \o \inlineimage windowsxp-label.png Screenshot of a Windows XP style label
|
---|
132 | \o A label shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
|
---|
133 | \endtable
|
---|
134 |
|
---|
135 | \sa QLineEdit, QTextEdit, QPixmap, QMovie,
|
---|
136 | {fowler}{GUI Design Handbook: Label}
|
---|
137 | */
|
---|
138 |
|
---|
139 | #ifndef QT_NO_PICTURE
|
---|
140 | /*!
|
---|
141 | Returns the label's picture or 0 if the label doesn't have a
|
---|
142 | picture.
|
---|
143 | */
|
---|
144 |
|
---|
145 | const QPicture *QLabel::picture() const
|
---|
146 | {
|
---|
147 | Q_D(const QLabel);
|
---|
148 | return d->picture;
|
---|
149 | }
|
---|
150 | #endif
|
---|
151 |
|
---|
152 |
|
---|
153 | /*!
|
---|
154 | Constructs an empty label.
|
---|
155 |
|
---|
156 | The \a parent and widget flag \a f, arguments are passed
|
---|
157 | to the QFrame constructor.
|
---|
158 |
|
---|
159 | \sa setAlignment(), setFrameStyle(), setIndent()
|
---|
160 | */
|
---|
161 | QLabel::QLabel(QWidget *parent, Qt::WindowFlags f)
|
---|
162 | : QFrame(*new QLabelPrivate(), parent, f)
|
---|
163 | {
|
---|
164 | Q_D(QLabel);
|
---|
165 | d->init();
|
---|
166 | }
|
---|
167 |
|
---|
168 | /*!
|
---|
169 | Constructs a label that displays the text, \a text.
|
---|
170 |
|
---|
171 | The \a parent and widget flag \a f, arguments are passed
|
---|
172 | to the QFrame constructor.
|
---|
173 |
|
---|
174 | \sa setText(), setAlignment(), setFrameStyle(), setIndent()
|
---|
175 | */
|
---|
176 | QLabel::QLabel(const QString &text, QWidget *parent, Qt::WindowFlags f)
|
---|
177 | : QFrame(*new QLabelPrivate(), parent, f)
|
---|
178 | {
|
---|
179 | Q_D(QLabel);
|
---|
180 | d->init();
|
---|
181 | setText(text);
|
---|
182 | }
|
---|
183 |
|
---|
184 |
|
---|
185 | #ifdef QT3_SUPPORT
|
---|
186 | /*! \obsolete
|
---|
187 | Constructs an empty label.
|
---|
188 |
|
---|
189 | The \a parent, \a name and widget flag \a f, arguments are passed
|
---|
190 | to the QFrame constructor.
|
---|
191 |
|
---|
192 | \sa setAlignment(), setFrameStyle(), setIndent()
|
---|
193 | */
|
---|
194 |
|
---|
195 | QLabel::QLabel(QWidget *parent, const char *name, Qt::WindowFlags f)
|
---|
196 | : QFrame(*new QLabelPrivate(), parent, f)
|
---|
197 | {
|
---|
198 | Q_D(QLabel);
|
---|
199 | if (name)
|
---|
200 | setObjectName(QString::fromAscii(name));
|
---|
201 | d->init();
|
---|
202 | }
|
---|
203 |
|
---|
204 |
|
---|
205 | /*! \obsolete
|
---|
206 | Constructs a label that displays the text, \a text.
|
---|
207 |
|
---|
208 | The \a parent, \a name and widget flag \a f, arguments are passed
|
---|
209 | to the QFrame constructor.
|
---|
210 |
|
---|
211 | \sa setText(), setAlignment(), setFrameStyle(), setIndent()
|
---|
212 | */
|
---|
213 |
|
---|
214 | QLabel::QLabel(const QString &text, QWidget *parent, const char *name,
|
---|
215 | Qt::WindowFlags f)
|
---|
216 | : QFrame(*new QLabelPrivate(), parent, f)
|
---|
217 | {
|
---|
218 | Q_D(QLabel);
|
---|
219 | if (name)
|
---|
220 | setObjectName(QString::fromAscii(name));
|
---|
221 | d->init();
|
---|
222 | setText(text);
|
---|
223 | }
|
---|
224 |
|
---|
225 |
|
---|
226 | /*! \obsolete
|
---|
227 | Constructs a label that displays the text \a text. The label has a
|
---|
228 | buddy widget, \a buddy.
|
---|
229 |
|
---|
230 | If the \a text contains an underlined letter (a letter preceded by
|
---|
231 | an ampersand, \&), when the user presses Alt+ the underlined letter,
|
---|
232 | focus is passed to the buddy widget.
|
---|
233 |
|
---|
234 | The \a parent, \a name and widget flag, \a f, arguments are passed
|
---|
235 | to the QFrame constructor.
|
---|
236 |
|
---|
237 | \sa setText(), setBuddy(), setAlignment(), setFrameStyle(),
|
---|
238 | setIndent()
|
---|
239 | */
|
---|
240 | QLabel::QLabel(QWidget *buddy, const QString &text,
|
---|
241 | QWidget *parent, const char *name, Qt::WindowFlags f)
|
---|
242 | : QFrame(*new QLabelPrivate(), parent, f)
|
---|
243 | {
|
---|
244 | Q_D(QLabel);
|
---|
245 | if (name)
|
---|
246 | setObjectName(QString::fromAscii(name));
|
---|
247 | d->init();
|
---|
248 | #ifndef QT_NO_SHORTCUT
|
---|
249 | setBuddy(buddy);
|
---|
250 | #endif
|
---|
251 | setText(text);
|
---|
252 | }
|
---|
253 | #endif //QT3_SUPPORT
|
---|
254 |
|
---|
255 | /*!
|
---|
256 | Destroys the label.
|
---|
257 | */
|
---|
258 |
|
---|
259 | QLabel::~QLabel()
|
---|
260 | {
|
---|
261 | Q_D(QLabel);
|
---|
262 | d->clearContents();
|
---|
263 | }
|
---|
264 |
|
---|
265 | void QLabelPrivate::init()
|
---|
266 | {
|
---|
267 | Q_Q(QLabel);
|
---|
268 |
|
---|
269 | valid_hints = false;
|
---|
270 | margin = 0;
|
---|
271 | #ifndef QT_NO_MOVIE
|
---|
272 | movie = 0;
|
---|
273 | #endif
|
---|
274 | #ifndef QT_NO_SHORTCUT
|
---|
275 | shortcutId = 0;
|
---|
276 | #endif
|
---|
277 | pixmap = 0;
|
---|
278 | scaledpixmap = 0;
|
---|
279 | cachedimage = 0;
|
---|
280 | #ifndef QT_NO_PICTURE
|
---|
281 | picture = 0;
|
---|
282 | #endif
|
---|
283 | align = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextExpandTabs;
|
---|
284 | indent = -1;
|
---|
285 | scaledcontents = false;
|
---|
286 | textLayoutDirty = false;
|
---|
287 | textDirty = false;
|
---|
288 | textformat = Qt::AutoText;
|
---|
289 | control = 0;
|
---|
290 | textInteractionFlags = Qt::LinksAccessibleByMouse;
|
---|
291 | isRichText = false;
|
---|
292 | isTextLabel = false;
|
---|
293 |
|
---|
294 | q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred,
|
---|
295 | QSizePolicy::Label));
|
---|
296 |
|
---|
297 | #ifndef QT_NO_CURSOR
|
---|
298 | validCursor = false;
|
---|
299 | onAnchor = false;
|
---|
300 | #endif
|
---|
301 |
|
---|
302 | openExternalLinks = false;
|
---|
303 |
|
---|
304 | setLayoutItemMargins(QStyle::SE_LabelLayoutItem);
|
---|
305 | }
|
---|
306 |
|
---|
307 |
|
---|
308 | /*!
|
---|
309 | \property QLabel::text
|
---|
310 | \brief the label's text
|
---|
311 |
|
---|
312 | If no text has been set this will return an empty string. Setting
|
---|
313 | the text clears any previous content.
|
---|
314 |
|
---|
315 | The text will be interpreted either as plain text or as rich
|
---|
316 | text, depending on the text format setting; see setTextFormat().
|
---|
317 | The default setting is Qt::AutoText; i.e. QLabel will try to
|
---|
318 | auto-detect the format of the text set.
|
---|
319 |
|
---|
320 | If a buddy has been set, the buddy mnemonic key is updated
|
---|
321 | from the new text.
|
---|
322 |
|
---|
323 | Note that QLabel is well-suited to display small rich text
|
---|
324 | documents, such as small documents that get their document
|
---|
325 | specific settings (font, text color, link color) from the label's
|
---|
326 | palette and font properties. For large documents, use QTextEdit
|
---|
327 | in read-only mode instead. QTextEdit can also provide a scroll bar
|
---|
328 | when necessary.
|
---|
329 |
|
---|
330 | \note This function enables mouse tracking if \a text contains rich
|
---|
331 | text.
|
---|
332 |
|
---|
333 | \sa setTextFormat(), setBuddy(), alignment
|
---|
334 | */
|
---|
335 |
|
---|
336 | void QLabel::setText(const QString &text)
|
---|
337 | {
|
---|
338 | Q_D(QLabel);
|
---|
339 | if (d->text == text)
|
---|
340 | return;
|
---|
341 |
|
---|
342 | QTextControl *oldControl = d->control;
|
---|
343 | d->control = 0;
|
---|
344 |
|
---|
345 | d->clearContents();
|
---|
346 | d->text = text;
|
---|
347 | d->isTextLabel = true;
|
---|
348 | d->textDirty = true;
|
---|
349 | d->isRichText = d->textformat == Qt::RichText
|
---|
350 | || (d->textformat == Qt::AutoText && Qt::mightBeRichText(d->text));
|
---|
351 |
|
---|
352 | d->control = oldControl;
|
---|
353 |
|
---|
354 | if (d->needTextControl()) {
|
---|
355 | d->ensureTextControl();
|
---|
356 | } else {
|
---|
357 | delete d->control;
|
---|
358 | d->control = 0;
|
---|
359 | }
|
---|
360 |
|
---|
361 | if (d->isRichText) {
|
---|
362 | setMouseTracking(true);
|
---|
363 | } else {
|
---|
364 | // Note: mouse tracking not disabled intentionally
|
---|
365 | }
|
---|
366 |
|
---|
367 | #ifndef QT_NO_SHORTCUT
|
---|
368 | if (d->buddy)
|
---|
369 | d->updateShortcut();
|
---|
370 | #endif
|
---|
371 |
|
---|
372 | d->updateLabel();
|
---|
373 | }
|
---|
374 |
|
---|
375 | QString QLabel::text() const
|
---|
376 | {
|
---|
377 | Q_D(const QLabel);
|
---|
378 | return d->text;
|
---|
379 | }
|
---|
380 |
|
---|
381 | /*!
|
---|
382 | Clears any label contents.
|
---|
383 | */
|
---|
384 |
|
---|
385 | void QLabel::clear()
|
---|
386 | {
|
---|
387 | Q_D(QLabel);
|
---|
388 | d->clearContents();
|
---|
389 | d->updateLabel();
|
---|
390 | }
|
---|
391 |
|
---|
392 | /*!
|
---|
393 | \property QLabel::pixmap
|
---|
394 | \brief the label's pixmap
|
---|
395 |
|
---|
396 | If no pixmap has been set this will return 0.
|
---|
397 |
|
---|
398 | Setting the pixmap clears any previous content. The buddy
|
---|
399 | shortcut, if any, is disabled.
|
---|
400 | */
|
---|
401 | void QLabel::setPixmap(const QPixmap &pixmap)
|
---|
402 | {
|
---|
403 | Q_D(QLabel);
|
---|
404 | if (!d->pixmap || d->pixmap->cacheKey() != pixmap.cacheKey()) {
|
---|
405 | d->clearContents();
|
---|
406 | d->pixmap = new QPixmap(pixmap);
|
---|
407 | }
|
---|
408 |
|
---|
409 | if (d->pixmap->depth() == 1 && !d->pixmap->mask())
|
---|
410 | d->pixmap->setMask(*((QBitmap *)d->pixmap));
|
---|
411 |
|
---|
412 | d->updateLabel();
|
---|
413 | }
|
---|
414 |
|
---|
415 | const QPixmap *QLabel::pixmap() const
|
---|
416 | {
|
---|
417 | Q_D(const QLabel);
|
---|
418 | return d->pixmap;
|
---|
419 | }
|
---|
420 |
|
---|
421 | #ifndef QT_NO_PICTURE
|
---|
422 | /*!
|
---|
423 | Sets the label contents to \a picture. Any previous content is
|
---|
424 | cleared.
|
---|
425 |
|
---|
426 | The buddy shortcut, if any, is disabled.
|
---|
427 |
|
---|
428 | \sa picture(), setBuddy()
|
---|
429 | */
|
---|
430 |
|
---|
431 | void QLabel::setPicture(const QPicture &picture)
|
---|
432 | {
|
---|
433 | Q_D(QLabel);
|
---|
434 | d->clearContents();
|
---|
435 | d->picture = new QPicture(picture);
|
---|
436 |
|
---|
437 | d->updateLabel();
|
---|
438 | }
|
---|
439 | #endif // QT_NO_PICTURE
|
---|
440 |
|
---|
441 | /*!
|
---|
442 | Sets the label contents to plain text containing the textual
|
---|
443 | representation of integer \a num. Any previous content is cleared.
|
---|
444 | Does nothing if the integer's string representation is the same as
|
---|
445 | the current contents of the label.
|
---|
446 |
|
---|
447 | The buddy shortcut, if any, is disabled.
|
---|
448 |
|
---|
449 | \sa setText(), QString::setNum(), setBuddy()
|
---|
450 | */
|
---|
451 |
|
---|
452 | void QLabel::setNum(int num)
|
---|
453 | {
|
---|
454 | QString str;
|
---|
455 | str.setNum(num);
|
---|
456 | setText(str);
|
---|
457 | }
|
---|
458 |
|
---|
459 | /*!
|
---|
460 | \overload
|
---|
461 |
|
---|
462 | Sets the label contents to plain text containing the textual
|
---|
463 | representation of double \a num. Any previous content is cleared.
|
---|
464 | Does nothing if the double's string representation is the same as
|
---|
465 | the current contents of the label.
|
---|
466 |
|
---|
467 | The buddy shortcut, if any, is disabled.
|
---|
468 |
|
---|
469 | \sa setText(), QString::setNum(), setBuddy()
|
---|
470 | */
|
---|
471 |
|
---|
472 | void QLabel::setNum(double num)
|
---|
473 | {
|
---|
474 | QString str;
|
---|
475 | str.setNum(num);
|
---|
476 | setText(str);
|
---|
477 | }
|
---|
478 |
|
---|
479 | /*!
|
---|
480 | \property QLabel::alignment
|
---|
481 | \brief the alignment of the label's contents
|
---|
482 |
|
---|
483 | By default, the contents of the label are left-aligned and vertically-centered.
|
---|
484 |
|
---|
485 | \sa text
|
---|
486 | */
|
---|
487 |
|
---|
488 | void QLabel::setAlignment(Qt::Alignment alignment)
|
---|
489 | {
|
---|
490 | Q_D(QLabel);
|
---|
491 | if (alignment == (d->align & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask)))
|
---|
492 | return;
|
---|
493 | d->align = (d->align & ~(Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask))
|
---|
494 | | (alignment & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask));
|
---|
495 |
|
---|
496 | d->updateLabel();
|
---|
497 | }
|
---|
498 |
|
---|
499 | #ifdef QT3_SUPPORT
|
---|
500 | /*!
|
---|
501 | Use setAlignment(Qt::Alignment) instead.
|
---|
502 |
|
---|
503 | If \a alignment specifies text flags as well, use setTextFormat()
|
---|
504 | to set those.
|
---|
505 | */
|
---|
506 | void QLabel::setAlignment(int alignment)
|
---|
507 | {
|
---|
508 | Q_D(QLabel);
|
---|
509 | d->align = alignment & ~(Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask|Qt::TextWordWrap);
|
---|
510 | setAlignment(Qt::Alignment(QFlag(alignment)));
|
---|
511 | }
|
---|
512 | #endif
|
---|
513 |
|
---|
514 | Qt::Alignment QLabel::alignment() const
|
---|
515 | {
|
---|
516 | Q_D(const QLabel);
|
---|
517 | return QFlag(d->align & (Qt::AlignVertical_Mask|Qt::AlignHorizontal_Mask));
|
---|
518 | }
|
---|
519 |
|
---|
520 |
|
---|
521 | /*!
|
---|
522 | \property QLabel::wordWrap
|
---|
523 | \brief the label's word-wrapping policy
|
---|
524 |
|
---|
525 | If this property is true then label text is wrapped where
|
---|
526 | necessary at word-breaks; otherwise it is not wrapped at all.
|
---|
527 |
|
---|
528 | By default, word wrap is disabled.
|
---|
529 |
|
---|
530 | \sa text
|
---|
531 | */
|
---|
532 | void QLabel::setWordWrap(bool on)
|
---|
533 | {
|
---|
534 | Q_D(QLabel);
|
---|
535 | if (on)
|
---|
536 | d->align |= Qt::TextWordWrap;
|
---|
537 | else
|
---|
538 | d->align &= ~Qt::TextWordWrap;
|
---|
539 |
|
---|
540 | d->updateLabel();
|
---|
541 | }
|
---|
542 |
|
---|
543 | bool QLabel::wordWrap() const
|
---|
544 | {
|
---|
545 | Q_D(const QLabel);
|
---|
546 | return d->align & Qt::TextWordWrap;
|
---|
547 | }
|
---|
548 |
|
---|
549 | /*!
|
---|
550 | \property QLabel::indent
|
---|
551 | \brief the label's text indent in pixels
|
---|
552 |
|
---|
553 | If a label displays text, the indent applies to the left edge if
|
---|
554 | alignment() is Qt::AlignLeft, to the right edge if alignment() is
|
---|
555 | Qt::AlignRight, to the top edge if alignment() is Qt::AlignTop, and
|
---|
556 | to to the bottom edge if alignment() is Qt::AlignBottom.
|
---|
557 |
|
---|
558 | If indent is negative, or if no indent has been set, the label
|
---|
559 | computes the effective indent as follows: If frameWidth() is 0,
|
---|
560 | the effective indent becomes 0. If frameWidth() is greater than 0,
|
---|
561 | the effective indent becomes half the width of the "x" character
|
---|
562 | of the widget's current font().
|
---|
563 |
|
---|
564 | By default, the indent is -1, meaning that an effective indent is
|
---|
565 | calculating in the manner described above.
|
---|
566 |
|
---|
567 | \sa alignment, margin, frameWidth(), font()
|
---|
568 | */
|
---|
569 |
|
---|
570 | void QLabel::setIndent(int indent)
|
---|
571 | {
|
---|
572 | Q_D(QLabel);
|
---|
573 | d->indent = indent;
|
---|
574 | d->updateLabel();
|
---|
575 | }
|
---|
576 |
|
---|
577 | int QLabel::indent() const
|
---|
578 | {
|
---|
579 | Q_D(const QLabel);
|
---|
580 | return d->indent;
|
---|
581 | }
|
---|
582 |
|
---|
583 |
|
---|
584 | /*!
|
---|
585 | \property QLabel::margin
|
---|
586 | \brief the width of the margin
|
---|
587 |
|
---|
588 | The margin is the distance between the innermost pixel of the
|
---|
589 | frame and the outermost pixel of contents.
|
---|
590 |
|
---|
591 | The default margin is 0.
|
---|
592 |
|
---|
593 | \sa indent
|
---|
594 | */
|
---|
595 | int QLabel::margin() const
|
---|
596 | {
|
---|
597 | Q_D(const QLabel);
|
---|
598 | return d->margin;
|
---|
599 | }
|
---|
600 |
|
---|
601 | void QLabel::setMargin(int margin)
|
---|
602 | {
|
---|
603 | Q_D(QLabel);
|
---|
604 | if (d->margin == margin)
|
---|
605 | return;
|
---|
606 | d->margin = margin;
|
---|
607 | d->updateLabel();
|
---|
608 | }
|
---|
609 |
|
---|
610 | /*!
|
---|
611 | Returns the size that will be used if the width of the label is \a
|
---|
612 | w. If \a w is -1, the sizeHint() is returned. If \a w is 0 minimumSizeHint() is returned
|
---|
613 | */
|
---|
614 | QSize QLabelPrivate::sizeForWidth(int w) const
|
---|
615 | {
|
---|
616 | Q_Q(const QLabel);
|
---|
617 | if(q->minimumWidth() > 0)
|
---|
618 | w = qMax(w, q->minimumWidth());
|
---|
619 | QSize contentsMargin(leftmargin + rightmargin, topmargin + bottommargin);
|
---|
620 |
|
---|
621 | QRect br;
|
---|
622 |
|
---|
623 | int hextra = 2 * margin;
|
---|
624 | int vextra = hextra;
|
---|
625 | QFontMetrics fm = q->fontMetrics();
|
---|
626 |
|
---|
627 | if (pixmap && !pixmap->isNull())
|
---|
628 | br = pixmap->rect();
|
---|
629 | #ifndef QT_NO_PICTURE
|
---|
630 | else if (picture && !picture->isNull())
|
---|
631 | br = picture->boundingRect();
|
---|
632 | #endif
|
---|
633 | #ifndef QT_NO_MOVIE
|
---|
634 | else if (movie && !movie->currentPixmap().isNull())
|
---|
635 | br = movie->currentPixmap().rect();
|
---|
636 | #endif
|
---|
637 | else if (isTextLabel) {
|
---|
638 | int align = QStyle::visualAlignment(textDirection(), QFlag(this->align));
|
---|
639 | // Add indentation
|
---|
640 | int m = indent;
|
---|
641 |
|
---|
642 | if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
|
---|
643 | m = fm.width(QLatin1Char('x')) - margin*2;
|
---|
644 | if (m > 0) {
|
---|
645 | if ((align & Qt::AlignLeft) || (align & Qt::AlignRight))
|
---|
646 | hextra += m;
|
---|
647 | if ((align & Qt::AlignTop) || (align & Qt::AlignBottom))
|
---|
648 | vextra += m;
|
---|
649 | }
|
---|
650 |
|
---|
651 | if (control) {
|
---|
652 | ensureTextLayouted();
|
---|
653 | const qreal oldTextWidth = control->textWidth();
|
---|
654 | // Calculate the length of document if w is the width
|
---|
655 | if (align & Qt::TextWordWrap) {
|
---|
656 | if (w >= 0) {
|
---|
657 | w = qMax(w-hextra-contentsMargin.width(), 0); // strip margin and indent
|
---|
658 | control->setTextWidth(w);
|
---|
659 | } else {
|
---|
660 | control->adjustSize();
|
---|
661 | }
|
---|
662 | } else {
|
---|
663 | control->setTextWidth(-1);
|
---|
664 | }
|
---|
665 |
|
---|
666 | QSizeF controlSize = control->size();
|
---|
667 | br = QRect(QPoint(0, 0), QSize(qCeil(controlSize.width()), qCeil(controlSize.height())));
|
---|
668 |
|
---|
669 | // restore state
|
---|
670 | control->setTextWidth(oldTextWidth);
|
---|
671 | } else {
|
---|
672 | // Turn off center alignment in order to avoid rounding errors for centering,
|
---|
673 | // since centering involves a division by 2. At the end, all we want is the size.
|
---|
674 | int flags = align & ~(Qt::AlignVCenter | Qt::AlignHCenter);
|
---|
675 | if (hasShortcut) {
|
---|
676 | flags |= Qt::TextShowMnemonic;
|
---|
677 | QStyleOption opt;
|
---|
678 | opt.initFrom(q);
|
---|
679 | if (!q->style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, q))
|
---|
680 | flags |= Qt::TextHideMnemonic;
|
---|
681 | }
|
---|
682 |
|
---|
683 | bool tryWidth = (w < 0) && (align & Qt::TextWordWrap);
|
---|
684 | if (tryWidth)
|
---|
685 | w = qMin(fm.averageCharWidth() * 80, q->maximumSize().width());
|
---|
686 | else if (w < 0)
|
---|
687 | w = 2000;
|
---|
688 | w -= (hextra + contentsMargin.width());
|
---|
689 | br = fm.boundingRect(0, 0, w ,2000, flags, text);
|
---|
690 | if (tryWidth && br.height() < 4*fm.lineSpacing() && br.width() > w/2)
|
---|
691 | br = fm.boundingRect(0, 0, w/2, 2000, flags, text);
|
---|
692 | if (tryWidth && br.height() < 2*fm.lineSpacing() && br.width() > w/4)
|
---|
693 | br = fm.boundingRect(0, 0, w/4, 2000, flags, text);
|
---|
694 | }
|
---|
695 | } else {
|
---|
696 | br = QRect(QPoint(0, 0), QSize(fm.averageCharWidth(), fm.lineSpacing()));
|
---|
697 | }
|
---|
698 |
|
---|
699 | const QSize contentsSize(br.width() + hextra, br.height() + vextra);
|
---|
700 | return (contentsSize + contentsMargin).expandedTo(q->minimumSize());
|
---|
701 | }
|
---|
702 |
|
---|
703 |
|
---|
704 | /*!
|
---|
705 | \reimp
|
---|
706 | */
|
---|
707 |
|
---|
708 | int QLabel::heightForWidth(int w) const
|
---|
709 | {
|
---|
710 | Q_D(const QLabel);
|
---|
711 | if (d->isTextLabel)
|
---|
712 | return d->sizeForWidth(w).height();
|
---|
713 | return QWidget::heightForWidth(w);
|
---|
714 | }
|
---|
715 |
|
---|
716 | /*!
|
---|
717 | \property QLabel::openExternalLinks
|
---|
718 | \since 4.2
|
---|
719 |
|
---|
720 | Specifies whether QLabel should automatically open links using
|
---|
721 | QDesktopServices::openUrl() instead of emitting the
|
---|
722 | linkActivated() signal.
|
---|
723 |
|
---|
724 | \bold{Note:} The textInteractionFlags set on the label need to include
|
---|
725 | either LinksAccessibleByMouse or LinksAccessibleByKeyboard.
|
---|
726 |
|
---|
727 | The default value is false.
|
---|
728 |
|
---|
729 | \sa textInteractionFlags()
|
---|
730 | */
|
---|
731 | bool QLabel::openExternalLinks() const
|
---|
732 | {
|
---|
733 | Q_D(const QLabel);
|
---|
734 | return d->openExternalLinks;
|
---|
735 | }
|
---|
736 |
|
---|
737 | void QLabel::setOpenExternalLinks(bool open)
|
---|
738 | {
|
---|
739 | Q_D(QLabel);
|
---|
740 | d->openExternalLinks = open;
|
---|
741 | if (d->control)
|
---|
742 | d->control->setOpenExternalLinks(open);
|
---|
743 | }
|
---|
744 |
|
---|
745 | /*!
|
---|
746 | \property QLabel::textInteractionFlags
|
---|
747 | \since 4.2
|
---|
748 |
|
---|
749 | Specifies how the label should interact with user input if it displays text.
|
---|
750 |
|
---|
751 | If the flags contain Qt::LinksAccessibleByKeyboard the focus policy is also
|
---|
752 | automatically set to Qt::StrongFocus. If Qt::TextSelectableByKeyboard is set
|
---|
753 | then the focus policy is set to Qt::ClickFocus.
|
---|
754 |
|
---|
755 | The default value is Qt::LinksAccessibleByMouse.
|
---|
756 | */
|
---|
757 | void QLabel::setTextInteractionFlags(Qt::TextInteractionFlags flags)
|
---|
758 | {
|
---|
759 | Q_D(QLabel);
|
---|
760 | if (d->textInteractionFlags == flags)
|
---|
761 | return;
|
---|
762 | d->textInteractionFlags = flags;
|
---|
763 | if (flags & Qt::LinksAccessibleByKeyboard)
|
---|
764 | setFocusPolicy(Qt::StrongFocus);
|
---|
765 | else if (flags & (Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse))
|
---|
766 | setFocusPolicy(Qt::ClickFocus);
|
---|
767 | else
|
---|
768 | setFocusPolicy(Qt::NoFocus);
|
---|
769 |
|
---|
770 | if (d->needTextControl()) {
|
---|
771 | d->ensureTextControl();
|
---|
772 | } else {
|
---|
773 | delete d->control;
|
---|
774 | d->control = 0;
|
---|
775 | }
|
---|
776 |
|
---|
777 | if (d->control)
|
---|
778 | d->control->setTextInteractionFlags(d->textInteractionFlags);
|
---|
779 | }
|
---|
780 |
|
---|
781 | Qt::TextInteractionFlags QLabel::textInteractionFlags() const
|
---|
782 | {
|
---|
783 | Q_D(const QLabel);
|
---|
784 | return d->textInteractionFlags;
|
---|
785 | }
|
---|
786 |
|
---|
787 | /*!
|
---|
788 | Selects text from position \a start and for \a length characters.
|
---|
789 |
|
---|
790 | \sa selectedText()
|
---|
791 |
|
---|
792 | \bold{Note:} The textInteractionFlags set on the label need to include
|
---|
793 | either TextSelectableByMouse or TextSelectableByKeyboard.
|
---|
794 |
|
---|
795 | \since 4.7
|
---|
796 | */
|
---|
797 | void QLabel::setSelection(int start, int length)
|
---|
798 | {
|
---|
799 | Q_D(QLabel);
|
---|
800 | if (d->control) {
|
---|
801 | d->ensureTextPopulated();
|
---|
802 | QTextCursor cursor = d->control->textCursor();
|
---|
803 | cursor.setPosition(start);
|
---|
804 | cursor.setPosition(start + length, QTextCursor::KeepAnchor);
|
---|
805 | d->control->setTextCursor(cursor);
|
---|
806 | }
|
---|
807 | }
|
---|
808 |
|
---|
809 | /*!
|
---|
810 | \property QLabel::hasSelectedText
|
---|
811 | \brief whether there is any text selected
|
---|
812 |
|
---|
813 | hasSelectedText() returns true if some or all of the text has been
|
---|
814 | selected by the user; otherwise returns false.
|
---|
815 |
|
---|
816 | By default, this property is false.
|
---|
817 |
|
---|
818 | \sa selectedText()
|
---|
819 |
|
---|
820 | \bold{Note:} The textInteractionFlags set on the label need to include
|
---|
821 | either TextSelectableByMouse or TextSelectableByKeyboard.
|
---|
822 |
|
---|
823 | \since 4.7
|
---|
824 | */
|
---|
825 | bool QLabel::hasSelectedText() const
|
---|
826 | {
|
---|
827 | Q_D(const QLabel);
|
---|
828 | if (d->control)
|
---|
829 | return d->control->textCursor().hasSelection();
|
---|
830 | return false;
|
---|
831 | }
|
---|
832 |
|
---|
833 | /*!
|
---|
834 | \property QLabel::selectedText
|
---|
835 | \brief the selected text
|
---|
836 |
|
---|
837 | If there is no selected text this property's value is
|
---|
838 | an empty string.
|
---|
839 |
|
---|
840 | By default, this property contains an empty string.
|
---|
841 |
|
---|
842 | \sa hasSelectedText()
|
---|
843 |
|
---|
844 | \bold{Note:} The textInteractionFlags set on the label need to include
|
---|
845 | either TextSelectableByMouse or TextSelectableByKeyboard.
|
---|
846 |
|
---|
847 | \since 4.7
|
---|
848 | */
|
---|
849 | QString QLabel::selectedText() const
|
---|
850 | {
|
---|
851 | Q_D(const QLabel);
|
---|
852 | if (d->control)
|
---|
853 | return d->control->textCursor().selectedText();
|
---|
854 | return QString();
|
---|
855 | }
|
---|
856 |
|
---|
857 | /*!
|
---|
858 | selectionStart() returns the index of the first selected character in the
|
---|
859 | label or -1 if no text is selected.
|
---|
860 |
|
---|
861 | \sa selectedText()
|
---|
862 |
|
---|
863 | \bold{Note:} The textInteractionFlags set on the label need to include
|
---|
864 | either TextSelectableByMouse or TextSelectableByKeyboard.
|
---|
865 |
|
---|
866 | \since 4.7
|
---|
867 | */
|
---|
868 | int QLabel::selectionStart() const
|
---|
869 | {
|
---|
870 | Q_D(const QLabel);
|
---|
871 | if (d->control && d->control->textCursor().hasSelection())
|
---|
872 | return d->control->textCursor().selectionStart();
|
---|
873 | return -1;
|
---|
874 | }
|
---|
875 |
|
---|
876 | /*!\reimp
|
---|
877 | */
|
---|
878 | QSize QLabel::sizeHint() const
|
---|
879 | {
|
---|
880 | Q_D(const QLabel);
|
---|
881 | if (!d->valid_hints)
|
---|
882 | (void) QLabel::minimumSizeHint();
|
---|
883 | return d->sh;
|
---|
884 | }
|
---|
885 |
|
---|
886 | /*!
|
---|
887 | \reimp
|
---|
888 | */
|
---|
889 | QSize QLabel::minimumSizeHint() const
|
---|
890 | {
|
---|
891 | Q_D(const QLabel);
|
---|
892 | if (d->valid_hints) {
|
---|
893 | if (d->sizePolicy == sizePolicy())
|
---|
894 | return d->msh;
|
---|
895 | }
|
---|
896 |
|
---|
897 | ensurePolished();
|
---|
898 | d->valid_hints = true;
|
---|
899 | d->sh = d->sizeForWidth(-1); // wrap ? golden ratio : min doc size
|
---|
900 | QSize msh(-1, -1);
|
---|
901 |
|
---|
902 | if (!d->isTextLabel) {
|
---|
903 | msh = d->sh;
|
---|
904 | } else {
|
---|
905 | msh.rheight() = d->sizeForWidth(QWIDGETSIZE_MAX).height(); // height for one line
|
---|
906 | msh.rwidth() = d->sizeForWidth(0).width(); // wrap ? size of biggest word : min doc size
|
---|
907 | if (d->sh.height() < msh.height())
|
---|
908 | msh.rheight() = d->sh.height();
|
---|
909 | }
|
---|
910 | d->msh = msh;
|
---|
911 | d->sizePolicy = sizePolicy();
|
---|
912 | return msh;
|
---|
913 | }
|
---|
914 |
|
---|
915 | /*!\reimp
|
---|
916 | */
|
---|
917 | void QLabel::mousePressEvent(QMouseEvent *ev)
|
---|
918 | {
|
---|
919 | Q_D(QLabel);
|
---|
920 | d->sendControlEvent(ev);
|
---|
921 | }
|
---|
922 |
|
---|
923 | /*!\reimp
|
---|
924 | */
|
---|
925 | void QLabel::mouseMoveEvent(QMouseEvent *ev)
|
---|
926 | {
|
---|
927 | Q_D(QLabel);
|
---|
928 | d->sendControlEvent(ev);
|
---|
929 | }
|
---|
930 |
|
---|
931 | /*!\reimp
|
---|
932 | */
|
---|
933 | void QLabel::mouseReleaseEvent(QMouseEvent *ev)
|
---|
934 | {
|
---|
935 | Q_D(QLabel);
|
---|
936 | d->sendControlEvent(ev);
|
---|
937 | }
|
---|
938 |
|
---|
939 | /*!\reimp
|
---|
940 | */
|
---|
941 | void QLabel::contextMenuEvent(QContextMenuEvent *ev)
|
---|
942 | {
|
---|
943 | #ifdef QT_NO_CONTEXTMENU
|
---|
944 | Q_UNUSED(ev);
|
---|
945 | #else
|
---|
946 | Q_D(QLabel);
|
---|
947 | if (!d->isTextLabel) {
|
---|
948 | ev->ignore();
|
---|
949 | return;
|
---|
950 | }
|
---|
951 | QMenu *menu = d->createStandardContextMenu(ev->pos());
|
---|
952 | if (!menu) {
|
---|
953 | ev->ignore();
|
---|
954 | return;
|
---|
955 | }
|
---|
956 | ev->accept();
|
---|
957 | menu->setAttribute(Qt::WA_DeleteOnClose);
|
---|
958 | menu->popup(ev->globalPos());
|
---|
959 | #endif
|
---|
960 | }
|
---|
961 |
|
---|
962 | /*!
|
---|
963 | \reimp
|
---|
964 | */
|
---|
965 | void QLabel::focusInEvent(QFocusEvent *ev)
|
---|
966 | {
|
---|
967 | Q_D(QLabel);
|
---|
968 | if (d->isTextLabel) {
|
---|
969 | d->ensureTextControl();
|
---|
970 | d->sendControlEvent(ev);
|
---|
971 | }
|
---|
972 | QFrame::focusInEvent(ev);
|
---|
973 | }
|
---|
974 |
|
---|
975 | /*!
|
---|
976 | \reimp
|
---|
977 | */
|
---|
978 | void QLabel::focusOutEvent(QFocusEvent *ev)
|
---|
979 | {
|
---|
980 | Q_D(QLabel);
|
---|
981 | if (d->control) {
|
---|
982 | d->sendControlEvent(ev);
|
---|
983 | QTextCursor cursor = d->control->textCursor();
|
---|
984 | Qt::FocusReason reason = ev->reason();
|
---|
985 | if (reason != Qt::ActiveWindowFocusReason
|
---|
986 | && reason != Qt::PopupFocusReason
|
---|
987 | && cursor.hasSelection()) {
|
---|
988 | cursor.clearSelection();
|
---|
989 | d->control->setTextCursor(cursor);
|
---|
990 | }
|
---|
991 | }
|
---|
992 |
|
---|
993 | QFrame::focusOutEvent(ev);
|
---|
994 | }
|
---|
995 |
|
---|
996 | /*!\reimp
|
---|
997 | */
|
---|
998 | bool QLabel::focusNextPrevChild(bool next)
|
---|
999 | {
|
---|
1000 | Q_D(QLabel);
|
---|
1001 | if (d->control && d->control->setFocusToNextOrPreviousAnchor(next))
|
---|
1002 | return true;
|
---|
1003 | return QFrame::focusNextPrevChild(next);
|
---|
1004 | }
|
---|
1005 |
|
---|
1006 | /*!\reimp
|
---|
1007 | */
|
---|
1008 | void QLabel::keyPressEvent(QKeyEvent *ev)
|
---|
1009 | {
|
---|
1010 | Q_D(QLabel);
|
---|
1011 | d->sendControlEvent(ev);
|
---|
1012 | }
|
---|
1013 |
|
---|
1014 | /*!\reimp
|
---|
1015 | */
|
---|
1016 | bool QLabel::event(QEvent *e)
|
---|
1017 | {
|
---|
1018 | Q_D(QLabel);
|
---|
1019 | QEvent::Type type = e->type();
|
---|
1020 |
|
---|
1021 | #ifndef QT_NO_SHORTCUT
|
---|
1022 | if (type == QEvent::Shortcut) {
|
---|
1023 | QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
|
---|
1024 | if (se->shortcutId() == d->shortcutId) {
|
---|
1025 | QWidget * w = d->buddy;
|
---|
1026 | QAbstractButton *button = qobject_cast<QAbstractButton *>(w);
|
---|
1027 | if (w->focusPolicy() != Qt::NoFocus)
|
---|
1028 | w->setFocus(Qt::ShortcutFocusReason);
|
---|
1029 | if (button && !se->isAmbiguous())
|
---|
1030 | button->animateClick();
|
---|
1031 | else
|
---|
1032 | window()->setAttribute(Qt::WA_KeyboardFocusChange);
|
---|
1033 | return true;
|
---|
1034 | }
|
---|
1035 | } else
|
---|
1036 | #endif
|
---|
1037 | if (type == QEvent::Resize) {
|
---|
1038 | if (d->control)
|
---|
1039 | d->textLayoutDirty = true;
|
---|
1040 | } else if (e->type() == QEvent::StyleChange
|
---|
1041 | #ifdef Q_WS_MAC
|
---|
1042 | || e->type() == QEvent::MacSizeChange
|
---|
1043 | #endif
|
---|
1044 | ) {
|
---|
1045 | d->setLayoutItemMargins(QStyle::SE_LabelLayoutItem);
|
---|
1046 | d->updateLabel();
|
---|
1047 | }
|
---|
1048 |
|
---|
1049 | return QFrame::event(e);
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 | /*!\reimp
|
---|
1053 | */
|
---|
1054 | void QLabel::paintEvent(QPaintEvent *)
|
---|
1055 | {
|
---|
1056 | Q_D(QLabel);
|
---|
1057 | QStyle *style = QWidget::style();
|
---|
1058 | QPainter painter(this);
|
---|
1059 | drawFrame(&painter);
|
---|
1060 | QRect cr = contentsRect();
|
---|
1061 | cr.adjust(d->margin, d->margin, -d->margin, -d->margin);
|
---|
1062 | int align = QStyle::visualAlignment(d->isTextLabel ? d->textDirection()
|
---|
1063 | : layoutDirection(), QFlag(d->align));
|
---|
1064 |
|
---|
1065 | #ifndef QT_NO_MOVIE
|
---|
1066 | if (d->movie) {
|
---|
1067 | if (d->scaledcontents)
|
---|
1068 | style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap().scaled(cr.size()));
|
---|
1069 | else
|
---|
1070 | style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap());
|
---|
1071 | }
|
---|
1072 | else
|
---|
1073 | #endif
|
---|
1074 | if (d->isTextLabel) {
|
---|
1075 | QRectF lr = d->layoutRect();
|
---|
1076 | QStyleOption opt;
|
---|
1077 | opt.initFrom(this);
|
---|
1078 | #ifndef QT_NO_STYLE_STYLESHEET
|
---|
1079 | if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) {
|
---|
1080 | cssStyle->styleSheetPalette(this, &opt, &opt.palette);
|
---|
1081 | }
|
---|
1082 | #endif
|
---|
1083 | if (d->control) {
|
---|
1084 | #ifndef QT_NO_SHORTCUT
|
---|
1085 | const bool underline = (bool)style->styleHint(QStyle::SH_UnderlineShortcut, 0, this, 0);
|
---|
1086 | if (d->shortcutId != 0
|
---|
1087 | && underline != d->shortcutCursor.charFormat().fontUnderline()) {
|
---|
1088 | QTextCharFormat fmt;
|
---|
1089 | fmt.setFontUnderline(underline);
|
---|
1090 | d->shortcutCursor.mergeCharFormat(fmt);
|
---|
1091 | }
|
---|
1092 | #endif
|
---|
1093 | d->ensureTextLayouted();
|
---|
1094 |
|
---|
1095 | QAbstractTextDocumentLayout::PaintContext context;
|
---|
1096 | if (!isEnabled() && !d->control &&
|
---|
1097 | // We cannot support etched for rich text controls because custom
|
---|
1098 | // colors and links will override the light palette
|
---|
1099 | style->styleHint(QStyle::SH_EtchDisabledText, &opt, this)) {
|
---|
1100 | context.palette = opt.palette;
|
---|
1101 | context.palette.setColor(QPalette::Text, context.palette.light().color());
|
---|
1102 | painter.save();
|
---|
1103 | painter.translate(lr.x() + 1, lr.y() + 1);
|
---|
1104 | painter.setClipRect(lr.translated(-lr.x() - 1, -lr.y() - 1));
|
---|
1105 | QAbstractTextDocumentLayout *layout = d->control->document()->documentLayout();
|
---|
1106 | layout->draw(&painter, context);
|
---|
1107 | painter.restore();
|
---|
1108 | }
|
---|
1109 |
|
---|
1110 | // Adjust the palette
|
---|
1111 | context.palette = opt.palette;
|
---|
1112 |
|
---|
1113 | if (foregroundRole() != QPalette::Text && isEnabled())
|
---|
1114 | context.palette.setColor(QPalette::Text, context.palette.color(foregroundRole()));
|
---|
1115 |
|
---|
1116 | painter.save();
|
---|
1117 | painter.translate(lr.topLeft());
|
---|
1118 | painter.setClipRect(lr.translated(-lr.x(), -lr.y()));
|
---|
1119 | d->control->setPalette(context.palette);
|
---|
1120 | d->control->drawContents(&painter, QRectF(), this);
|
---|
1121 | painter.restore();
|
---|
1122 | } else {
|
---|
1123 | int flags = align | (d->textDirection() == Qt::LeftToRight ? Qt::TextForceLeftToRight
|
---|
1124 | : Qt::TextForceRightToLeft);
|
---|
1125 | if (d->hasShortcut) {
|
---|
1126 | flags |= Qt::TextShowMnemonic;
|
---|
1127 | if (!style->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
|
---|
1128 | flags |= Qt::TextHideMnemonic;
|
---|
1129 | }
|
---|
1130 | style->drawItemText(&painter, lr.toRect(), flags, opt.palette, isEnabled(), d->text, foregroundRole());
|
---|
1131 | }
|
---|
1132 | } else
|
---|
1133 | #ifndef QT_NO_PICTURE
|
---|
1134 | if (d->picture) {
|
---|
1135 | QRect br = d->picture->boundingRect();
|
---|
1136 | int rw = br.width();
|
---|
1137 | int rh = br.height();
|
---|
1138 | if (d->scaledcontents) {
|
---|
1139 | painter.save();
|
---|
1140 | painter.translate(cr.x(), cr.y());
|
---|
1141 | painter.scale((double)cr.width()/rw, (double)cr.height()/rh);
|
---|
1142 | painter.drawPicture(-br.x(), -br.y(), *d->picture);
|
---|
1143 | painter.restore();
|
---|
1144 | } else {
|
---|
1145 | int xo = 0;
|
---|
1146 | int yo = 0;
|
---|
1147 | if (align & Qt::AlignVCenter)
|
---|
1148 | yo = (cr.height()-rh)/2;
|
---|
1149 | else if (align & Qt::AlignBottom)
|
---|
1150 | yo = cr.height()-rh;
|
---|
1151 | if (align & Qt::AlignRight)
|
---|
1152 | xo = cr.width()-rw;
|
---|
1153 | else if (align & Qt::AlignHCenter)
|
---|
1154 | xo = (cr.width()-rw)/2;
|
---|
1155 | painter.drawPicture(cr.x()+xo-br.x(), cr.y()+yo-br.y(), *d->picture);
|
---|
1156 | }
|
---|
1157 | } else
|
---|
1158 | #endif
|
---|
1159 | if (d->pixmap && !d->pixmap->isNull()) {
|
---|
1160 | QPixmap pix;
|
---|
1161 | if (d->scaledcontents) {
|
---|
1162 | if (!d->scaledpixmap || d->scaledpixmap->size() != cr.size()) {
|
---|
1163 | if (!d->cachedimage)
|
---|
1164 | d->cachedimage = new QImage(d->pixmap->toImage());
|
---|
1165 | delete d->scaledpixmap;
|
---|
1166 | d->scaledpixmap = new QPixmap(QPixmap::fromImage(d->cachedimage->scaled(cr.size(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation)));
|
---|
1167 | }
|
---|
1168 | pix = *d->scaledpixmap;
|
---|
1169 | } else
|
---|
1170 | pix = *d->pixmap;
|
---|
1171 | QStyleOption opt;
|
---|
1172 | opt.initFrom(this);
|
---|
1173 | if (!isEnabled())
|
---|
1174 | pix = style->generatedIconPixmap(QIcon::Disabled, pix, &opt);
|
---|
1175 | style->drawItemPixmap(&painter, cr, align, pix);
|
---|
1176 | }
|
---|
1177 | }
|
---|
1178 |
|
---|
1179 |
|
---|
1180 | /*!
|
---|
1181 | Updates the label, but not the frame.
|
---|
1182 | */
|
---|
1183 |
|
---|
1184 | void QLabelPrivate::updateLabel()
|
---|
1185 | {
|
---|
1186 | Q_Q(QLabel);
|
---|
1187 | valid_hints = false;
|
---|
1188 |
|
---|
1189 | if (isTextLabel) {
|
---|
1190 | QSizePolicy policy = q->sizePolicy();
|
---|
1191 | const bool wrap = align & Qt::TextWordWrap;
|
---|
1192 | policy.setHeightForWidth(wrap);
|
---|
1193 | if (policy != q->sizePolicy()) // ### should be replaced by WA_WState_OwnSizePolicy idiom
|
---|
1194 | q->setSizePolicy(policy);
|
---|
1195 | textLayoutDirty = true;
|
---|
1196 | }
|
---|
1197 | q->updateGeometry();
|
---|
1198 | q->update(q->contentsRect());
|
---|
1199 | }
|
---|
1200 |
|
---|
1201 | #ifndef QT_NO_SHORTCUT
|
---|
1202 | /*!
|
---|
1203 | Sets this label's buddy to \a buddy.
|
---|
1204 |
|
---|
1205 | When the user presses the shortcut key indicated by this label,
|
---|
1206 | the keyboard focus is transferred to the label's buddy widget.
|
---|
1207 |
|
---|
1208 | The buddy mechanism is only available for QLabels that contain
|
---|
1209 | text in which one character is prefixed with an ampersand, '&'.
|
---|
1210 | This character is set as the shortcut key. See the \l
|
---|
1211 | QKeySequence::mnemonic() documentation for details (to display an
|
---|
1212 | actual ampersand, use '&&').
|
---|
1213 |
|
---|
1214 | In a dialog, you might create two data entry widgets and a label
|
---|
1215 | for each, and set up the geometry layout so each label is just to
|
---|
1216 | the left of its data entry widget (its "buddy"), for example:
|
---|
1217 | \snippet doc/src/snippets/code/src_gui_widgets_qlabel.cpp 2
|
---|
1218 |
|
---|
1219 | With the code above, the focus jumps to the Name field when the
|
---|
1220 | user presses Alt+N, and to the Phone field when the user presses
|
---|
1221 | Alt+P.
|
---|
1222 |
|
---|
1223 | To unset a previously set buddy, call this function with \a buddy
|
---|
1224 | set to 0.
|
---|
1225 |
|
---|
1226 | \sa buddy(), setText(), QShortcut, setAlignment()
|
---|
1227 | */
|
---|
1228 |
|
---|
1229 | void QLabel::setBuddy(QWidget *buddy)
|
---|
1230 | {
|
---|
1231 | Q_D(QLabel);
|
---|
1232 | d->buddy = buddy;
|
---|
1233 | if (d->isTextLabel) {
|
---|
1234 | if (d->shortcutId)
|
---|
1235 | releaseShortcut(d->shortcutId);
|
---|
1236 | d->shortcutId = 0;
|
---|
1237 | d->textDirty = true;
|
---|
1238 | if (buddy)
|
---|
1239 | d->updateShortcut(); // grab new shortcut
|
---|
1240 | d->updateLabel();
|
---|
1241 | }
|
---|
1242 | }
|
---|
1243 |
|
---|
1244 |
|
---|
1245 | /*!
|
---|
1246 | Returns this label's buddy, or 0 if no buddy is currently set.
|
---|
1247 |
|
---|
1248 | \sa setBuddy()
|
---|
1249 | */
|
---|
1250 |
|
---|
1251 | QWidget * QLabel::buddy() const
|
---|
1252 | {
|
---|
1253 | Q_D(const QLabel);
|
---|
1254 | return d->buddy;
|
---|
1255 | }
|
---|
1256 |
|
---|
1257 | void QLabelPrivate::updateShortcut()
|
---|
1258 | {
|
---|
1259 | Q_Q(QLabel);
|
---|
1260 | Q_ASSERT(shortcutId == 0);
|
---|
1261 | // Introduce an extra boolean to indicate the presence of a shortcut in the
|
---|
1262 | // text. We cannot use the shortcutId itself because on the mac mnemonics are
|
---|
1263 | // off by default, so QKeySequence::mnemonic always returns an empty sequence.
|
---|
1264 | // But then we do want to hide the ampersands, so we can't use shortcutId.
|
---|
1265 | hasShortcut = false;
|
---|
1266 |
|
---|
1267 | if (!text.contains(QLatin1Char('&')))
|
---|
1268 | return;
|
---|
1269 | hasShortcut = true;
|
---|
1270 | shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
|
---|
1271 | }
|
---|
1272 |
|
---|
1273 | #endif // QT_NO_SHORTCUT
|
---|
1274 |
|
---|
1275 | #ifndef QT_NO_MOVIE
|
---|
1276 | void QLabelPrivate::_q_movieUpdated(const QRect& rect)
|
---|
1277 | {
|
---|
1278 | Q_Q(QLabel);
|
---|
1279 | if (movie && movie->isValid()) {
|
---|
1280 | QRect r;
|
---|
1281 | if (scaledcontents) {
|
---|
1282 | QRect cr = q->contentsRect();
|
---|
1283 | QRect pixmapRect(cr.topLeft(), movie->currentPixmap().size());
|
---|
1284 | if (pixmapRect.isEmpty())
|
---|
1285 | return;
|
---|
1286 | r.setRect(cr.left(), cr.top(),
|
---|
1287 | (rect.width() * cr.width()) / pixmapRect.width(),
|
---|
1288 | (rect.height() * cr.height()) / pixmapRect.height());
|
---|
1289 | } else {
|
---|
1290 | r = q->style()->itemPixmapRect(q->contentsRect(), align, movie->currentPixmap());
|
---|
1291 | r.translate(rect.x(), rect.y());
|
---|
1292 | r.setWidth(qMin(r.width(), rect.width()));
|
---|
1293 | r.setHeight(qMin(r.height(), rect.height()));
|
---|
1294 | }
|
---|
1295 | q->update(r);
|
---|
1296 | }
|
---|
1297 | }
|
---|
1298 |
|
---|
1299 | void QLabelPrivate::_q_movieResized(const QSize& size)
|
---|
1300 | {
|
---|
1301 | Q_Q(QLabel);
|
---|
1302 | q->update(); //we need to refresh the whole background in case the new size is smaler
|
---|
1303 | valid_hints = false;
|
---|
1304 | _q_movieUpdated(QRect(QPoint(0,0), size));
|
---|
1305 | q->updateGeometry();
|
---|
1306 | }
|
---|
1307 |
|
---|
1308 | /*!
|
---|
1309 | Sets the label contents to \a movie. Any previous content is
|
---|
1310 | cleared. The label does NOT take ownership of the movie.
|
---|
1311 |
|
---|
1312 | The buddy shortcut, if any, is disabled.
|
---|
1313 |
|
---|
1314 | \sa movie(), setBuddy()
|
---|
1315 | */
|
---|
1316 |
|
---|
1317 | void QLabel::setMovie(QMovie *movie)
|
---|
1318 | {
|
---|
1319 | Q_D(QLabel);
|
---|
1320 | d->clearContents();
|
---|
1321 |
|
---|
1322 | if (!movie)
|
---|
1323 | return;
|
---|
1324 |
|
---|
1325 | d->movie = movie;
|
---|
1326 | connect(movie, SIGNAL(resized(QSize)), this, SLOT(_q_movieResized(QSize)));
|
---|
1327 | connect(movie, SIGNAL(updated(QRect)), this, SLOT(_q_movieUpdated(QRect)));
|
---|
1328 |
|
---|
1329 | // Assume that if the movie is running,
|
---|
1330 | // resize/update signals will come soon enough
|
---|
1331 | if (movie->state() != QMovie::Running)
|
---|
1332 | d->updateLabel();
|
---|
1333 | }
|
---|
1334 |
|
---|
1335 | #endif // QT_NO_MOVIE
|
---|
1336 |
|
---|
1337 | /*!
|
---|
1338 | \internal
|
---|
1339 |
|
---|
1340 | Clears any contents, without updating/repainting the label.
|
---|
1341 | */
|
---|
1342 |
|
---|
1343 | void QLabelPrivate::clearContents()
|
---|
1344 | {
|
---|
1345 | delete control;
|
---|
1346 | control = 0;
|
---|
1347 | isTextLabel = false;
|
---|
1348 | hasShortcut = false;
|
---|
1349 |
|
---|
1350 | #ifndef QT_NO_PICTURE
|
---|
1351 | delete picture;
|
---|
1352 | picture = 0;
|
---|
1353 | #endif
|
---|
1354 | delete scaledpixmap;
|
---|
1355 | scaledpixmap = 0;
|
---|
1356 | delete cachedimage;
|
---|
1357 | cachedimage = 0;
|
---|
1358 | delete pixmap;
|
---|
1359 | pixmap = 0;
|
---|
1360 |
|
---|
1361 | text.clear();
|
---|
1362 | Q_Q(QLabel);
|
---|
1363 | #ifndef QT_NO_SHORTCUT
|
---|
1364 | if (shortcutId)
|
---|
1365 | q->releaseShortcut(shortcutId);
|
---|
1366 | shortcutId = 0;
|
---|
1367 | #endif
|
---|
1368 | #ifndef QT_NO_MOVIE
|
---|
1369 | if (movie) {
|
---|
1370 | QObject::disconnect(movie, SIGNAL(resized(QSize)), q, SLOT(_q_movieResized(QSize)));
|
---|
1371 | QObject::disconnect(movie, SIGNAL(updated(QRect)), q, SLOT(_q_movieUpdated(QRect)));
|
---|
1372 | }
|
---|
1373 | movie = 0;
|
---|
1374 | #endif
|
---|
1375 | #ifndef QT_NO_CURSOR
|
---|
1376 | if (onAnchor) {
|
---|
1377 | if (validCursor)
|
---|
1378 | q->setCursor(cursor);
|
---|
1379 | else
|
---|
1380 | q->unsetCursor();
|
---|
1381 | }
|
---|
1382 | validCursor = false;
|
---|
1383 | onAnchor = false;
|
---|
1384 | #endif
|
---|
1385 | }
|
---|
1386 |
|
---|
1387 |
|
---|
1388 | #ifndef QT_NO_MOVIE
|
---|
1389 |
|
---|
1390 | /*!
|
---|
1391 | Returns a pointer to the label's movie, or 0 if no movie has been
|
---|
1392 | set.
|
---|
1393 |
|
---|
1394 | \sa setMovie()
|
---|
1395 | */
|
---|
1396 |
|
---|
1397 | QMovie *QLabel::movie() const
|
---|
1398 | {
|
---|
1399 | Q_D(const QLabel);
|
---|
1400 | return d->movie;
|
---|
1401 | }
|
---|
1402 |
|
---|
1403 | #endif // QT_NO_MOVIE
|
---|
1404 |
|
---|
1405 | /*!
|
---|
1406 | \property QLabel::textFormat
|
---|
1407 | \brief the label's text format
|
---|
1408 |
|
---|
1409 | See the Qt::TextFormat enum for an explanation of the possible
|
---|
1410 | options.
|
---|
1411 |
|
---|
1412 | The default format is Qt::AutoText.
|
---|
1413 |
|
---|
1414 | \sa text()
|
---|
1415 | */
|
---|
1416 |
|
---|
1417 | Qt::TextFormat QLabel::textFormat() const
|
---|
1418 | {
|
---|
1419 | Q_D(const QLabel);
|
---|
1420 | return d->textformat;
|
---|
1421 | }
|
---|
1422 |
|
---|
1423 | void QLabel::setTextFormat(Qt::TextFormat format)
|
---|
1424 | {
|
---|
1425 | Q_D(QLabel);
|
---|
1426 | if (format != d->textformat) {
|
---|
1427 | d->textformat = format;
|
---|
1428 | QString t = d->text;
|
---|
1429 | if (!t.isNull()) {
|
---|
1430 | d->text.clear();
|
---|
1431 | setText(t);
|
---|
1432 | }
|
---|
1433 | }
|
---|
1434 | }
|
---|
1435 |
|
---|
1436 | /*!
|
---|
1437 | \reimp
|
---|
1438 | */
|
---|
1439 | void QLabel::changeEvent(QEvent *ev)
|
---|
1440 | {
|
---|
1441 | Q_D(QLabel);
|
---|
1442 | if(ev->type() == QEvent::FontChange || ev->type() == QEvent::ApplicationFontChange) {
|
---|
1443 | if (d->isTextLabel) {
|
---|
1444 | if (d->control)
|
---|
1445 | d->control->document()->setDefaultFont(font());
|
---|
1446 | d->updateLabel();
|
---|
1447 | }
|
---|
1448 | } else if (ev->type() == QEvent::PaletteChange && d->control) {
|
---|
1449 | d->control->setPalette(palette());
|
---|
1450 | } else if (ev->type() == QEvent::ContentsRectChange) {
|
---|
1451 | d->updateLabel();
|
---|
1452 | }
|
---|
1453 | QFrame::changeEvent(ev);
|
---|
1454 | }
|
---|
1455 |
|
---|
1456 | /*!
|
---|
1457 | \property QLabel::scaledContents
|
---|
1458 | \brief whether the label will scale its contents to fill all
|
---|
1459 | available space.
|
---|
1460 |
|
---|
1461 | When enabled and the label shows a pixmap, it will scale the
|
---|
1462 | pixmap to fill the available space.
|
---|
1463 |
|
---|
1464 | This property's default is false.
|
---|
1465 | */
|
---|
1466 | bool QLabel::hasScaledContents() const
|
---|
1467 | {
|
---|
1468 | Q_D(const QLabel);
|
---|
1469 | return d->scaledcontents;
|
---|
1470 | }
|
---|
1471 |
|
---|
1472 | void QLabel::setScaledContents(bool enable)
|
---|
1473 | {
|
---|
1474 | Q_D(QLabel);
|
---|
1475 | if ((bool)d->scaledcontents == enable)
|
---|
1476 | return;
|
---|
1477 | d->scaledcontents = enable;
|
---|
1478 | if (!enable) {
|
---|
1479 | delete d->scaledpixmap;
|
---|
1480 | d->scaledpixmap = 0;
|
---|
1481 | delete d->cachedimage;
|
---|
1482 | d->cachedimage = 0;
|
---|
1483 | }
|
---|
1484 | update(contentsRect());
|
---|
1485 | }
|
---|
1486 |
|
---|
1487 | Qt::LayoutDirection QLabelPrivate::textDirection() const
|
---|
1488 | {
|
---|
1489 | if (control) {
|
---|
1490 | QTextOption opt = control->document()->defaultTextOption();
|
---|
1491 | return opt.textDirection();
|
---|
1492 | }
|
---|
1493 |
|
---|
1494 | return text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight;
|
---|
1495 | }
|
---|
1496 |
|
---|
1497 | /*!
|
---|
1498 | \fn void QLabel::setAlignment(Qt::AlignmentFlag flag)
|
---|
1499 | \internal
|
---|
1500 |
|
---|
1501 | Without this function, a call to e.g. setAlignment(Qt::AlignTop)
|
---|
1502 | results in the \c QT3_SUPPORT function setAlignment(int) being called,
|
---|
1503 | rather than setAlignment(Qt::Alignment).
|
---|
1504 | */
|
---|
1505 |
|
---|
1506 | // Returns the rect that is available for us to draw the document
|
---|
1507 | QRect QLabelPrivate::documentRect() const
|
---|
1508 | {
|
---|
1509 | Q_Q(const QLabel);
|
---|
1510 | Q_ASSERT_X(isTextLabel, "documentRect", "document rect called for label that is not a text label!");
|
---|
1511 | QRect cr = q->contentsRect();
|
---|
1512 | cr.adjust(margin, margin, -margin, -margin);
|
---|
1513 | const int align = QStyle::visualAlignment(isTextLabel ? textDirection()
|
---|
1514 | : q->layoutDirection(), QFlag(this->align));
|
---|
1515 | int m = indent;
|
---|
1516 | if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
|
---|
1517 | m = q->fontMetrics().width(QLatin1Char('x')) / 2 - margin;
|
---|
1518 | if (m > 0) {
|
---|
1519 | if (align & Qt::AlignLeft)
|
---|
1520 | cr.setLeft(cr.left() + m);
|
---|
1521 | if (align & Qt::AlignRight)
|
---|
1522 | cr.setRight(cr.right() - m);
|
---|
1523 | if (align & Qt::AlignTop)
|
---|
1524 | cr.setTop(cr.top() + m);
|
---|
1525 | if (align & Qt::AlignBottom)
|
---|
1526 | cr.setBottom(cr.bottom() - m);
|
---|
1527 | }
|
---|
1528 | return cr;
|
---|
1529 | }
|
---|
1530 |
|
---|
1531 | void QLabelPrivate::ensureTextPopulated() const
|
---|
1532 | {
|
---|
1533 | if (!textDirty)
|
---|
1534 | return;
|
---|
1535 | if (control) {
|
---|
1536 | QTextDocument *doc = control->document();
|
---|
1537 | if (textDirty) {
|
---|
1538 | #ifndef QT_NO_TEXTHTMLPARSER
|
---|
1539 | if (isRichText)
|
---|
1540 | doc->setHtml(text);
|
---|
1541 | else
|
---|
1542 | doc->setPlainText(text);
|
---|
1543 | #else
|
---|
1544 | doc->setPlainText(text);
|
---|
1545 | #endif
|
---|
1546 | doc->setUndoRedoEnabled(false);
|
---|
1547 |
|
---|
1548 | #ifndef QT_NO_SHORTCUT
|
---|
1549 | if (hasShortcut) {
|
---|
1550 | // Underline the first character that follows an ampersand (and remove the others ampersands)
|
---|
1551 | int from = 0;
|
---|
1552 | bool found = false;
|
---|
1553 | QTextCursor cursor;
|
---|
1554 | while (!(cursor = control->document()->find((QLatin1String("&")), from)).isNull()) {
|
---|
1555 | cursor.deleteChar(); // remove the ampersand
|
---|
1556 | cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
|
---|
1557 | from = cursor.position();
|
---|
1558 | if (!found && cursor.selectedText() != QLatin1String("&")) { //not a second &
|
---|
1559 | found = true;
|
---|
1560 | shortcutCursor = cursor;
|
---|
1561 | }
|
---|
1562 | }
|
---|
1563 | }
|
---|
1564 | #endif
|
---|
1565 | }
|
---|
1566 | }
|
---|
1567 | textDirty = false;
|
---|
1568 | }
|
---|
1569 |
|
---|
1570 | void QLabelPrivate::ensureTextLayouted() const
|
---|
1571 | {
|
---|
1572 | if (!textLayoutDirty)
|
---|
1573 | return;
|
---|
1574 | ensureTextPopulated();
|
---|
1575 | if (control) {
|
---|
1576 | QTextDocument *doc = control->document();
|
---|
1577 | QTextOption opt = doc->defaultTextOption();
|
---|
1578 |
|
---|
1579 | opt.setAlignment(QFlag(this->align));
|
---|
1580 |
|
---|
1581 | if (this->align & Qt::TextWordWrap)
|
---|
1582 | opt.setWrapMode(QTextOption::WordWrap);
|
---|
1583 | else
|
---|
1584 | opt.setWrapMode(QTextOption::ManualWrap);
|
---|
1585 |
|
---|
1586 | doc->setDefaultTextOption(opt);
|
---|
1587 |
|
---|
1588 | QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
|
---|
1589 | fmt.setMargin(0);
|
---|
1590 | doc->rootFrame()->setFrameFormat(fmt);
|
---|
1591 | doc->setTextWidth(documentRect().width());
|
---|
1592 | }
|
---|
1593 | textLayoutDirty = false;
|
---|
1594 | }
|
---|
1595 |
|
---|
1596 | void QLabelPrivate::ensureTextControl() const
|
---|
1597 | {
|
---|
1598 | Q_Q(const QLabel);
|
---|
1599 | if (!isTextLabel)
|
---|
1600 | return;
|
---|
1601 | if (!control) {
|
---|
1602 | control = new QTextControl(const_cast<QLabel *>(q));
|
---|
1603 | control->document()->setUndoRedoEnabled(false);
|
---|
1604 | control->document()->setDefaultFont(q->font());
|
---|
1605 | control->setTextInteractionFlags(textInteractionFlags);
|
---|
1606 | control->setOpenExternalLinks(openExternalLinks);
|
---|
1607 | control->setPalette(q->palette());
|
---|
1608 | control->setFocus(q->hasFocus());
|
---|
1609 | QObject::connect(control, SIGNAL(updateRequest(QRectF)),
|
---|
1610 | q, SLOT(update()));
|
---|
1611 | QObject::connect(control, SIGNAL(linkHovered(QString)),
|
---|
1612 | q, SLOT(_q_linkHovered(QString)));
|
---|
1613 | QObject::connect(control, SIGNAL(linkActivated(QString)),
|
---|
1614 | q, SIGNAL(linkActivated(QString)));
|
---|
1615 | textLayoutDirty = true;
|
---|
1616 | textDirty = true;
|
---|
1617 | }
|
---|
1618 | }
|
---|
1619 |
|
---|
1620 | void QLabelPrivate::sendControlEvent(QEvent *e)
|
---|
1621 | {
|
---|
1622 | Q_Q(QLabel);
|
---|
1623 | if (!isTextLabel || !control || textInteractionFlags == Qt::NoTextInteraction) {
|
---|
1624 | e->ignore();
|
---|
1625 | return;
|
---|
1626 | }
|
---|
1627 | control->processEvent(e, -layoutRect().topLeft(), q);
|
---|
1628 | }
|
---|
1629 |
|
---|
1630 | void QLabelPrivate::_q_linkHovered(const QString &anchor)
|
---|
1631 | {
|
---|
1632 | Q_Q(QLabel);
|
---|
1633 | #ifndef QT_NO_CURSOR
|
---|
1634 | if (anchor.isEmpty()) { // restore cursor
|
---|
1635 | if (validCursor)
|
---|
1636 | q->setCursor(cursor);
|
---|
1637 | else
|
---|
1638 | q->unsetCursor();
|
---|
1639 | onAnchor = false;
|
---|
1640 | } else if (!onAnchor) {
|
---|
1641 | validCursor = q->testAttribute(Qt::WA_SetCursor);
|
---|
1642 | if (validCursor) {
|
---|
1643 | cursor = q->cursor();
|
---|
1644 | }
|
---|
1645 | q->setCursor(Qt::PointingHandCursor);
|
---|
1646 | onAnchor = true;
|
---|
1647 | }
|
---|
1648 | #endif
|
---|
1649 | emit q->linkHovered(anchor);
|
---|
1650 | }
|
---|
1651 |
|
---|
1652 | // Return the layout rect - this is the rect that is given to the layout painting code
|
---|
1653 | // This may be different from the document rect since vertical alignment is not
|
---|
1654 | // done by the text layout code
|
---|
1655 | QRectF QLabelPrivate::layoutRect() const
|
---|
1656 | {
|
---|
1657 | QRectF cr = documentRect();
|
---|
1658 | if (!control)
|
---|
1659 | return cr;
|
---|
1660 | ensureTextLayouted();
|
---|
1661 | // Caculate y position manually
|
---|
1662 | qreal rh = control->document()->documentLayout()->documentSize().height();
|
---|
1663 | qreal yo = 0;
|
---|
1664 | if (align & Qt::AlignVCenter)
|
---|
1665 | yo = qMax((cr.height()-rh)/2, qreal(0));
|
---|
1666 | else if (align & Qt::AlignBottom)
|
---|
1667 | yo = qMax(cr.height()-rh, qreal(0));
|
---|
1668 | return QRectF(cr.x(), yo + cr.y(), cr.width(), cr.height());
|
---|
1669 | }
|
---|
1670 |
|
---|
1671 | // Returns the point in the document rect adjusted with p
|
---|
1672 | QPoint QLabelPrivate::layoutPoint(const QPoint& p) const
|
---|
1673 | {
|
---|
1674 | QRect lr = layoutRect().toRect();
|
---|
1675 | return p - lr.topLeft();
|
---|
1676 | }
|
---|
1677 |
|
---|
1678 | #ifndef QT_NO_CONTEXTMENU
|
---|
1679 | QMenu *QLabelPrivate::createStandardContextMenu(const QPoint &pos)
|
---|
1680 | {
|
---|
1681 | QString linkToCopy;
|
---|
1682 | QPoint p;
|
---|
1683 | if (control && isRichText) {
|
---|
1684 | p = layoutPoint(pos);
|
---|
1685 | linkToCopy = control->document()->documentLayout()->anchorAt(p);
|
---|
1686 | }
|
---|
1687 |
|
---|
1688 | if (linkToCopy.isEmpty() && !control)
|
---|
1689 | return 0;
|
---|
1690 |
|
---|
1691 | return control->createStandardContextMenu(p, q_func());
|
---|
1692 | }
|
---|
1693 | #endif
|
---|
1694 |
|
---|
1695 | /*!
|
---|
1696 | \fn void QLabel::linkHovered(const QString &link)
|
---|
1697 | \since 4.2
|
---|
1698 |
|
---|
1699 | This signal is emitted when the user hovers over a link. The URL
|
---|
1700 | referred to by the anchor is passed in \a link.
|
---|
1701 |
|
---|
1702 | \sa linkActivated()
|
---|
1703 | */
|
---|
1704 |
|
---|
1705 |
|
---|
1706 | /*!
|
---|
1707 | \fn void QLabel::linkActivated(const QString &link)
|
---|
1708 | \since 4.2
|
---|
1709 |
|
---|
1710 | This signal is emitted when the user clicks a link. The URL
|
---|
1711 | referred to by the anchor is passed in \a link.
|
---|
1712 |
|
---|
1713 | \sa linkHovered()
|
---|
1714 | */
|
---|
1715 |
|
---|
1716 | QT_END_NAMESPACE
|
---|
1717 |
|
---|
1718 | #include "moc_qlabel.cpp"
|
---|