source: trunk/src/gui/widgets/qframe.cpp@ 858

Last change on this file since 858 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 15.5 KB
Line 
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 "qframe.h"
43#include "qbitmap.h"
44#include "qdrawutil.h"
45#include "qevent.h"
46#include "qpainter.h"
47#include "qstyle.h"
48#include "qstyleoption.h"
49#include "qapplication.h"
50
51#include "qframe_p.h"
52
53QT_BEGIN_NAMESPACE
54
55QFramePrivate::QFramePrivate()
56 : frect(QRect(0, 0, 0, 0)),
57 frameStyle(QFrame::NoFrame | QFrame::Plain),
58 lineWidth(1),
59 midLineWidth(0),
60 frameWidth(0),
61 leftFrameWidth(0), rightFrameWidth(0),
62 topFrameWidth(0), bottomFrameWidth(0)
63{
64}
65
66inline void QFramePrivate::init()
67{
68 setLayoutItemMargins(QStyle::SE_FrameLayoutItem);
69}
70
71/*!
72 \class QFrame
73 \brief The QFrame class is the base class of widgets that can have a frame.
74
75 \ingroup abstractwidgets
76
77
78 QMenu uses this to "raise" the menu above the surrounding
79 screen. QProgressBar has a "sunken" look. QLabel has a flat look.
80 The frames of widgets like these can be changed.
81
82 \snippet doc/src/snippets/code/src_gui_widgets_qframe.cpp 0
83
84 The QFrame class can also be used directly for creating simple
85 placeholder frames without any contents.
86
87 The frame style is specified by a \l{QFrame::Shape}{frame shape} and
88 a \l{QFrame::Shadow}{shadow style} that is used to visually separate
89 the frame from surrounding widgets. These properties can be set
90 together using the setFrameStyle() function and read with frameStyle().
91
92 The frame shapes are \l NoFrame, \l Box, \l Panel, \l StyledPanel,
93 HLine and \l VLine; the shadow styles are \l Plain, \l Raised and
94 \l Sunken.
95
96 A frame widget has three attributes that describe the thickness of the
97 border: \l lineWidth, \l midLineWidth, and \l frameWidth.
98
99 \list
100 \o The line width is the width of the frame border. It can be modified
101 to customize the frame's appearance.
102
103 \o The mid-line width specifies the width of an extra line in the
104 middle of the frame, which uses a third color to obtain a special
105 3D effect. Notice that a mid-line is only drawn for \l Box, \l
106 HLine and \l VLine frames that are raised or sunken.
107
108 \o The frame width is determined by the frame style, and the frameWidth()
109 function is used to obtain the value defined for the style used.
110 \endlist
111
112 The margin between the frame and the contents of the frame can be
113 customized with the QWidget::setContentsMargins() function.
114
115 \target picture
116 This table shows some of the combinations of styles and line widths:
117
118 \image frames.png Table of frame styles
119*/
120
121
122/*!
123 \enum QFrame::Shape
124
125 This enum type defines the shapes of frame available.
126
127 \value NoFrame QFrame draws nothing
128 \value Box QFrame draws a box around its contents
129 \value Panel QFrame draws a panel to make the contents appear
130 raised or sunken
131 \value StyledPanel draws a rectangular panel with a look that
132 depends on the current GUI style. It can be raised or sunken.
133 \value HLine QFrame draws a horizontal line that frames nothing
134 (useful as separator)
135 \value VLine QFrame draws a vertical line that frames nothing
136 (useful as separator)
137 \value WinPanel draws a rectangular panel that can be raised or
138 sunken like those in Windows 2000. Specifying this shape sets
139 the line width to 2 pixels. WinPanel is provided for compatibility.
140 For GUI style independence we recommend using StyledPanel instead.
141
142 \omitvalue GroupBoxPanel
143 \omitvalue ToolBarPanel
144 \omitvalue MenuBarPanel
145 \omitvalue PopupPanel
146 \omitvalue LineEditPanel
147 \omitvalue TabWidgetPanel
148
149 When it does not call QStyle, Shape interacts with QFrame::Shadow,
150 the lineWidth() and the midLineWidth() to create the total result.
151 See the picture of the frames in the main class documentation.
152
153 \sa QFrame::Shadow QFrame::style() QStyle::drawPrimitive()
154*/
155
156
157/*!
158 \enum QFrame::Shadow
159
160 This enum type defines the types of shadow that are used to give
161 a 3D effect to frames.
162
163 \value Plain the frame and contents appear level with the
164 surroundings; draws using the palette QPalette::WindowText color
165 (without any 3D effect)
166
167 \value Raised the frame and contents appear raised; draws a 3D
168 raised line using the light and dark colors of the current color
169 group
170 \value Sunken the frame and contents appear sunken; draws a 3D
171 sunken line using the light and dark colors of the current color
172 group
173
174 Shadow interacts with QFrame::Shape, the lineWidth() and the
175 midLineWidth(). See the picture of the frames in the main class
176 documentation.
177
178 \sa QFrame::Shape lineWidth() midLineWidth()
179*/
180
181/*!
182 \enum QFrame::StyleMask
183
184 This enum defines two constants that can be used to extract the
185 two components of frameStyle():
186
187 \value Shadow_Mask The \l Shadow part of frameStyle()
188 \value Shape_Mask The \l Shape part of frameStyle()
189
190 \omitvalue MShadow
191 \omitvalue MShape
192
193 Normally, you don't need to use these, since frameShadow() and
194 frameShape() already extract the \l Shadow and the \l Shape parts
195 of frameStyle().
196
197 \sa frameStyle(), setFrameStyle()
198*/
199
200/*!
201 Constructs a frame widget with frame style \l NoFrame and a
202 1-pixel frame width.
203
204 The \a parent and \a f arguments are passed to the QWidget
205 constructor.
206*/
207
208QFrame::QFrame(QWidget* parent, Qt::WindowFlags f)
209 : QWidget(*new QFramePrivate, parent, f)
210{
211 Q_D(QFrame);
212 d->init();
213}
214
215/*! \internal */
216QFrame::QFrame(QFramePrivate &dd, QWidget* parent, Qt::WindowFlags f)
217 : QWidget(dd, parent, f)
218{
219 Q_D(QFrame);
220 d->init();
221}
222
223#ifdef QT3_SUPPORT
224/*!
225 Use one of the constructors that doesn't take the \a name
226 argument and then use setObjectName() instead.
227*/
228QFrame::QFrame(QWidget *parent, const char *name, Qt::WindowFlags f)
229 : QWidget(*new QFramePrivate, parent, f)
230{
231 Q_D(QFrame);
232 setObjectName(QString::fromAscii(name));
233 d->init();
234}
235#endif
236
237/*!
238 Destroys the frame.
239 */
240QFrame::~QFrame()
241{
242}
243
244/*!
245 Returns the frame style.
246
247 The default value is QFrame::Plain.
248
249 \sa setFrameStyle(), frameShape(), frameShadow()
250*/
251int QFrame::frameStyle() const
252{
253 Q_D(const QFrame);
254 return d->frameStyle;
255}
256
257/*!
258 \property QFrame::frameShape
259 \brief the frame shape value from the frame style
260
261 \sa frameStyle(), frameShadow()
262*/
263
264QFrame::Shape QFrame::frameShape() const
265{
266 Q_D(const QFrame);
267 return (Shape) (d->frameStyle & Shape_Mask);
268}
269
270void QFrame::setFrameShape(QFrame::Shape s)
271{
272 Q_D(QFrame);
273 setFrameStyle((d->frameStyle & Shadow_Mask) | s);
274}
275
276
277/*!
278 \property QFrame::frameShadow
279 \brief the frame shadow value from the frame style
280
281 \sa frameStyle(), frameShape()
282*/
283QFrame::Shadow QFrame::frameShadow() const
284{
285 Q_D(const QFrame);
286 return (Shadow) (d->frameStyle & Shadow_Mask);
287}
288
289void QFrame::setFrameShadow(QFrame::Shadow s)
290{
291 Q_D(QFrame);
292 setFrameStyle((d->frameStyle & Shape_Mask) | s);
293}
294
295/*!
296 Sets the frame style to \a style.
297
298 The \a style is the bitwise OR between a frame shape and a frame
299 shadow style. See the picture of the frames in the main class
300 documentation.
301
302 The frame shapes are given in \l{QFrame::Shape} and the shadow
303 styles in \l{QFrame::Shadow}.
304
305 If a mid-line width greater than 0 is specified, an additional
306 line is drawn for \l Raised or \l Sunken \l Box, \l HLine, and \l
307 VLine frames. The mid-color of the current color group is used for
308 drawing middle lines.
309
310 \sa frameStyle()
311*/
312
313void QFrame::setFrameStyle(int style)
314{
315 Q_D(QFrame);
316 if (!testAttribute(Qt::WA_WState_OwnSizePolicy)) {
317 QSizePolicy sp;
318
319 switch (style & Shape_Mask) {
320 case HLine:
321 sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::Line);
322 break;
323 case VLine:
324 sp = QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum, QSizePolicy::Line);
325 break;
326 default:
327 sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::Frame);
328 }
329 setSizePolicy(sp);
330 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
331 }
332 d->frameStyle = (short)style;
333 update();
334 d->updateFrameWidth();
335}
336
337/*!
338 \property QFrame::lineWidth
339 \brief the line width
340
341 Note that the \e total line width for frames used as separators
342 (\l HLine and \l VLine) is specified by \l frameWidth.
343
344 The default value is 1.
345
346 \sa midLineWidth, frameWidth
347*/
348
349void QFrame::setLineWidth(int w)
350{
351 Q_D(QFrame);
352 if (short(w) == d->lineWidth)
353 return;
354 d->lineWidth = short(w);
355 d->updateFrameWidth();
356}
357
358int QFrame::lineWidth() const
359{
360 Q_D(const QFrame);
361 return d->lineWidth;
362}
363
364/*!
365 \property QFrame::midLineWidth
366 \brief the width of the mid-line
367
368 The default value is 0.
369
370 \sa lineWidth, frameWidth
371*/
372
373void QFrame::setMidLineWidth(int w)
374{
375 Q_D(QFrame);
376 if (short(w) == d->midLineWidth)
377 return;
378 d->midLineWidth = short(w);
379 d->updateFrameWidth();
380}
381
382int QFrame::midLineWidth() const
383{
384 Q_D(const QFrame);
385 return d->midLineWidth;
386}
387
388/*!
389 \internal
390 Updates the frame widths from the style.
391*/
392void QFramePrivate::updateStyledFrameWidths()
393{
394 Q_Q(const QFrame);
395 QStyleOptionFrameV3 opt;
396 opt.initFrom(q);
397 opt.lineWidth = lineWidth;
398 opt.midLineWidth = midLineWidth;
399 opt.frameShape = QFrame::Shape(frameStyle & QFrame::Shape_Mask);
400
401 QRect cr = q->style()->subElementRect(QStyle::SE_ShapedFrameContents, &opt, q);
402 leftFrameWidth = cr.left() - opt.rect.left();
403 topFrameWidth = cr.top() - opt.rect.top();
404 rightFrameWidth = opt.rect.right() - cr.right(),
405 bottomFrameWidth = opt.rect.bottom() - cr.bottom();
406 frameWidth = qMax(qMax(leftFrameWidth, rightFrameWidth),
407 qMax(topFrameWidth, bottomFrameWidth));
408}
409
410/*!
411 \internal
412 Updated the frameWidth parameter.
413*/
414
415void QFramePrivate::updateFrameWidth()
416{
417 Q_Q(QFrame);
418 QRect fr = q->frameRect();
419 updateStyledFrameWidths();
420 q->setFrameRect(fr);
421 setLayoutItemMargins(QStyle::SE_FrameLayoutItem);
422}
423
424/*!
425 \property QFrame::frameWidth
426 \brief the width of the frame that is drawn.
427
428 Note that the frame width depends on the \l{QFrame::setFrameStyle()}{frame style},
429 not only the line width and the mid-line width. For example, the style specified
430 by \l NoFrame always has a frame width of 0, whereas the style \l Panel has a
431 frame width equivalent to the line width.
432
433 \sa lineWidth(), midLineWidth(), frameStyle()
434*/
435int QFrame::frameWidth() const
436{
437 Q_D(const QFrame);
438 return d->frameWidth;
439}
440
441
442/*!
443 \property QFrame::frameRect
444 \brief the frame's rectangle
445
446 The frame's rectangle is the rectangle the frame is drawn in. By
447 default, this is the entire widget. Setting the rectangle does
448 does \e not cause a widget update. The frame rectangle is
449 automatically adjusted when the widget changes size.
450
451 If you set the rectangle to a null rectangle (for example,
452 QRect(0, 0, 0, 0)), then the resulting frame rectangle is
453 equivalent to the \link QWidget::rect() widget rectangle\endlink.
454*/
455
456QRect QFrame::frameRect() const
457{
458 Q_D(const QFrame);
459 QRect fr = contentsRect();
460 fr.adjust(-d->leftFrameWidth, -d->topFrameWidth, d->rightFrameWidth, d->bottomFrameWidth);
461 return fr;
462}
463
464void QFrame::setFrameRect(const QRect &r)
465{
466 Q_D(QFrame);
467 QRect cr = r.isValid() ? r : rect();
468 cr.adjust(d->leftFrameWidth, d->topFrameWidth, -d->rightFrameWidth, -d->bottomFrameWidth);
469 setContentsMargins(cr.left(), cr.top(), rect().right() - cr.right(), rect().bottom() - cr.bottom());
470}
471
472/*!\reimp
473*/
474QSize QFrame::sizeHint() const
475{
476 Q_D(const QFrame);
477 // Returns a size hint for the frame - for HLine and VLine
478 // shapes, this is stretchable one way and 3 pixels wide the
479 // other. For other shapes, QWidget::sizeHint() is used.
480 switch (d->frameStyle & Shape_Mask) {
481 case HLine:
482 return QSize(-1,3);
483 case VLine:
484 return QSize(3,-1);
485 default:
486 return QWidget::sizeHint();
487 }
488}
489
490/*!\reimp
491*/
492
493void QFrame::paintEvent(QPaintEvent *)
494{
495 QPainter paint(this);
496 drawFrame(&paint);
497}
498
499/*!
500 \internal
501
502 Mostly for the sake of Q3Frame
503 */
504void QFrame::drawFrame(QPainter *p)
505{
506 Q_D(QFrame);
507 QStyleOptionFrameV3 opt;
508 opt.init(this);
509 int frameShape = d->frameStyle & QFrame::Shape_Mask;
510 int frameShadow = d->frameStyle & QFrame::Shadow_Mask;
511 opt.frameShape = Shape(int(opt.frameShape) | frameShape);
512 opt.rect = frameRect();
513 switch (frameShape) {
514 case QFrame::Box:
515 case QFrame::HLine:
516 case QFrame::VLine:
517 case QFrame::StyledPanel:
518 case QFrame::Panel:
519 opt.lineWidth = d->lineWidth;
520 opt.midLineWidth = d->midLineWidth;
521 break;
522 default:
523 // most frame styles do not handle customized line and midline widths
524 // (see updateFrameWidth()).
525 opt.lineWidth = d->frameWidth;
526 break;
527 }
528
529 if (frameShadow == Sunken)
530 opt.state |= QStyle::State_Sunken;
531 else if (frameShadow == Raised)
532 opt.state |= QStyle::State_Raised;
533
534 style()->drawControl(QStyle::CE_ShapedFrame, &opt, p, this);
535}
536
537
538/*!\reimp
539 */
540void QFrame::changeEvent(QEvent *ev)
541{
542 Q_D(QFrame);
543 if (ev->type() == QEvent::StyleChange
544#ifdef Q_WS_MAC
545 || ev->type() == QEvent::MacSizeChange
546#endif
547 )
548 d->updateFrameWidth();
549 QWidget::changeEvent(ev);
550}
551
552/*! \reimp */
553bool QFrame::event(QEvent *e)
554{
555 if (e->type() == QEvent::ParentChange)
556 d_func()->updateFrameWidth();
557 bool result = QWidget::event(e);
558 //this has to be done after the widget has been polished
559 if (e->type() == QEvent::Polish)
560 d_func()->updateFrameWidth();
561 return result;
562}
563
564QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.