source: ntrip/trunk/BNC/qwt/qwt_arrow_button.cpp@ 8150

Last change on this file since 8150 was 8127, checked in by stoecker, 8 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

File size: 8.1 KB
RevLine 
[8127]1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_arrow_button.h"
11#include "qwt_math.h"
12#include <qpainter.h>
13#include <qstyle.h>
14#include <qstyleoption.h>
15#include <qevent.h>
16#include <qapplication.h>
17
18static const int MaxNum = 3;
19static const int Margin = 2;
20static const int Spacing = 1;
21
22class QwtArrowButton::PrivateData
23{
24public:
25 int num;
26 Qt::ArrowType arrowType;
27};
28
29static QStyleOptionButton styleOpt( const QwtArrowButton* btn )
30{
31 QStyleOptionButton option;
32 option.init( btn );
33 option.features = QStyleOptionButton::None;
34 if ( btn->isFlat() )
35 option.features |= QStyleOptionButton::Flat;
36 if ( btn->menu() )
37 option.features |= QStyleOptionButton::HasMenu;
38 if ( btn->autoDefault() || btn->isDefault() )
39 option.features |= QStyleOptionButton::AutoDefaultButton;
40 if ( btn->isDefault() )
41 option.features |= QStyleOptionButton::DefaultButton;
42 if ( btn->isDown() )
43 option.state |= QStyle::State_Sunken;
44 if ( !btn->isFlat() && !btn->isDown() )
45 option.state |= QStyle::State_Raised;
46
47 return option;
48}
49
50/*!
51 \param num Number of arrows
52 \param arrowType see Qt::ArrowType in the Qt docs.
53 \param parent Parent widget
54*/
55QwtArrowButton::QwtArrowButton( int num,
56 Qt::ArrowType arrowType, QWidget *parent ):
57 QPushButton( parent )
58{
59 d_data = new PrivateData;
60 d_data->num = qBound( 1, num, MaxNum );
61 d_data->arrowType = arrowType;
62
63 setAutoRepeat( true );
64 setAutoDefault( false );
65
66 switch ( d_data->arrowType )
67 {
68 case Qt::LeftArrow:
69 case Qt::RightArrow:
70 setSizePolicy( QSizePolicy::Expanding,
71 QSizePolicy::Fixed );
72 break;
73 default:
74 setSizePolicy( QSizePolicy::Fixed,
75 QSizePolicy::Expanding );
76 }
77}
78
79//! Destructor
80QwtArrowButton::~QwtArrowButton()
81{
82 delete d_data;
83 d_data = NULL;
84}
85
86/*!
87 \brief The direction of the arrows
88*/
89Qt::ArrowType QwtArrowButton::arrowType() const
90{
91 return d_data->arrowType;
92}
93
94/*!
95 \brief The number of arrows
96*/
97int QwtArrowButton::num() const
98{
99 return d_data->num;
100}
101
102/*!
103 \return the bounding rectangle for the label
104*/
105QRect QwtArrowButton::labelRect() const
106{
107 const int m = Margin;
108
109 QRect r = rect();
110 r.setRect( r.x() + m, r.y() + m,
111 r.width() - 2 * m, r.height() - 2 * m );
112
113 if ( isDown() )
114 {
115 QStyleOptionButton option = styleOpt( this );
116 const int ph = style()->pixelMetric(
117 QStyle::PM_ButtonShiftHorizontal, &option, this );
118 const int pv = style()->pixelMetric(
119 QStyle::PM_ButtonShiftVertical, &option, this );
120
121 r.translate( ph, pv );
122 }
123
124 return r;
125}
126
127/*!
128 Paint event handler
129 \param event Paint event
130*/
131void QwtArrowButton::paintEvent( QPaintEvent *event )
132{
133 QPushButton::paintEvent( event );
134 QPainter painter( this );
135 drawButtonLabel( &painter );
136}
137
138/*!
139 \brief Draw the button label
140
141 \param painter Painter
142 \sa The Qt Manual for QPushButton
143*/
144void QwtArrowButton::drawButtonLabel( QPainter *painter )
145{
146 const bool isVertical = d_data->arrowType == Qt::UpArrow ||
147 d_data->arrowType == Qt::DownArrow;
148
149 const QRect r = labelRect();
150 QSize boundingSize = labelRect().size();
151 if ( isVertical )
152 boundingSize.transpose();
153
154 const int w =
155 ( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum;
156
157 QSize arrow = arrowSize( Qt::RightArrow,
158 QSize( w, boundingSize.height() ) );
159
160 if ( isVertical )
161 arrow.transpose();
162
163 QRect contentsSize; // aligned rect where to paint all arrows
164 if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow )
165 {
166 contentsSize.setWidth( d_data->num * arrow.width()
167 + ( d_data->num - 1 ) * Spacing );
168 contentsSize.setHeight( arrow.height() );
169 }
170 else
171 {
172 contentsSize.setWidth( arrow.width() );
173 contentsSize.setHeight( d_data->num * arrow.height()
174 + ( d_data->num - 1 ) * Spacing );
175 }
176
177 QRect arrowRect( contentsSize );
178 arrowRect.moveCenter( r.center() );
179 arrowRect.setSize( arrow );
180
181 painter->save();
182 for ( int i = 0; i < d_data->num; i++ )
183 {
184 drawArrow( painter, arrowRect, d_data->arrowType );
185
186 int dx = 0;
187 int dy = 0;
188
189 if ( isVertical )
190 dy = arrow.height() + Spacing;
191 else
192 dx = arrow.width() + Spacing;
193
194 arrowRect.translate( dx, dy );
195 }
196 painter->restore();
197
198 if ( hasFocus() )
199 {
200 QStyleOptionFocusRect option;
201 option.init( this );
202 option.backgroundColor = palette().color( QPalette::Window );
203
204 style()->drawPrimitive( QStyle::PE_FrameFocusRect,
205 &option, painter, this );
206 }
207}
208
209/*!
210 Draw an arrow int a bounding rectangle
211
212 \param painter Painter
213 \param r Rectangle where to paint the arrow
214 \param arrowType Arrow type
215*/
216void QwtArrowButton::drawArrow( QPainter *painter,
217 const QRect &r, Qt::ArrowType arrowType ) const
218{
219 QPolygon pa( 3 );
220
221 switch ( arrowType )
222 {
223 case Qt::UpArrow:
224 pa.setPoint( 0, r.bottomLeft() );
225 pa.setPoint( 1, r.bottomRight() );
226 pa.setPoint( 2, r.center().x(), r.top() );
227 break;
228 case Qt::DownArrow:
229 pa.setPoint( 0, r.topLeft() );
230 pa.setPoint( 1, r.topRight() );
231 pa.setPoint( 2, r.center().x(), r.bottom() );
232 break;
233 case Qt::RightArrow:
234 pa.setPoint( 0, r.topLeft() );
235 pa.setPoint( 1, r.bottomLeft() );
236 pa.setPoint( 2, r.right(), r.center().y() );
237 break;
238 case Qt::LeftArrow:
239 pa.setPoint( 0, r.topRight() );
240 pa.setPoint( 1, r.bottomRight() );
241 pa.setPoint( 2, r.left(), r.center().y() );
242 break;
243 default:
244 break;
245 }
246
247 painter->save();
248
249 painter->setRenderHint( QPainter::Antialiasing, true );
250 painter->setPen( Qt::NoPen );
251 painter->setBrush( palette().brush( QPalette::ButtonText ) );
252 painter->drawPolygon( pa );
253
254 painter->restore();
255}
256
257/*!
258 \return a size hint
259*/
260QSize QwtArrowButton::sizeHint() const
261{
262 const QSize hint = minimumSizeHint();
263 return hint.expandedTo( QApplication::globalStrut() );
264}
265
266/*!
267 \brief Return a minimum size hint
268*/
269QSize QwtArrowButton::minimumSizeHint() const
270{
271 const QSize asz = arrowSize( Qt::RightArrow, QSize() );
272
273 QSize sz(
274 2 * Margin + ( MaxNum - 1 ) * Spacing + MaxNum * asz.width(),
275 2 * Margin + asz.height()
276 );
277
278 if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow )
279 sz.transpose();
280
281 QStyleOption styleOption;
282 styleOption.init( this );
283
284 sz = style()->sizeFromContents( QStyle::CT_PushButton,
285 &styleOption, sz, this );
286
287 return sz;
288}
289
290/*!
291 Calculate the size for a arrow that fits into a rectangle of a given size
292
293 \param arrowType Arrow type
294 \param boundingSize Bounding size
295 \return Size of the arrow
296*/
297QSize QwtArrowButton::arrowSize( Qt::ArrowType arrowType,
298 const QSize &boundingSize ) const
299{
300 QSize bs = boundingSize;
301 if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
302 bs.transpose();
303
304 const int MinLen = 2;
305 const QSize sz = bs.expandedTo(
306 QSize( MinLen, 2 * MinLen - 1 ) ); // minimum
307
308 int w = sz.width();
309 int h = 2 * w - 1;
310
311 if ( h > sz.height() )
312 {
313 h = sz.height();
314 w = ( h + 1 ) / 2;
315 }
316
317 QSize arrSize( w, h );
318 if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
319 arrSize.transpose();
320
321 return arrSize;
322}
323
324/*!
325 \brief autoRepeat for the space keys
326*/
327void QwtArrowButton::keyPressEvent( QKeyEvent *event )
328{
329 if ( event->isAutoRepeat() && event->key() == Qt::Key_Space )
330 Q_EMIT clicked();
331
332 QPushButton::keyPressEvent( event );
333}
Note: See TracBrowser for help on using the repository browser.