QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskRadioBox.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskRadioBox.h"
7#include "QskEvent.h"
8#include "QskAnimationHint.h"
9#include "QskSkinlet.h"
10
11QSK_SUBCONTROL( QskRadioBox, Panel )
12QSK_SUBCONTROL( QskRadioBox, Button )
13QSK_SUBCONTROL( QskRadioBox, CheckIndicatorPanel )
14QSK_SUBCONTROL( QskRadioBox, CheckIndicator )
15QSK_SUBCONTROL( QskRadioBox, Text )
16
17QSK_STATE( QskRadioBox, Selected, QskAspect::FirstUserState << 1 )
18QSK_STATE( QskRadioBox, Pressed, QskAspect::FirstUserState << 2 )
19
20class QskRadioBox::PrivateData
21{
22 public:
23 QStringList options;
24
25 int selectedIndex = -1;
26 int hoveredIndex = -1;
27 int focusedIndex = -1;
28 int pressedIndex = -1;
29};
30
31QskRadioBox::QskRadioBox( QQuickItem* parent )
32 : Inherited( parent )
33 , m_data( new PrivateData() )
34{
35 initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
36
37 setFocusPolicy( Qt::StrongFocus );
38 setAcceptedMouseButtons( Qt::LeftButton );
39
40 setPositionHint( CheckIndicator, -1 );
41
42 setAcceptHoverEvents( true );
43}
44
45QskRadioBox::QskRadioBox( const QStringList& options, QQuickItem* parent )
46 : QskRadioBox( parent )
47{
48 setOptions( options );
49}
50
51QskRadioBox::QskRadioBox( const QStringList& items,
52 int selectedIndex, QQuickItem* parent )
53 : QskRadioBox( items, parent )
54{
55 if( selectedIndex >= 0 && selectedIndex < items.count() )
56 m_data->selectedIndex = selectedIndex;
57}
58
59QskRadioBox::~QskRadioBox()
60{
61}
62
64{
65 if ( m_data->focusedIndex < 0 )
66 return QRectF();
67
68 const auto rect = contentsRect();
69
71
72 const auto panelRect = skinlet->sampleRect( this,
73 rect, QskRadioBox::CheckIndicatorPanel, m_data->focusedIndex );
74
75 auto y = panelRect.y();
76 auto h = panelRect.height();
77
78 const auto textRect = skinlet->sampleRect( this,
79 rect, QskRadioBox::Text, m_data->focusedIndex );
80
81 if( textRect.height() > 0.0 )
82 {
83 y = qMin( y, textRect.y() );
84 h = qMax( h, textRect.height() );
85 }
86
87 return QRectF( rect.x(), y, rect.width(), h );
88}
89
90int QskRadioBox::selectedIndex() const
91{
92 return m_data->selectedIndex;
93}
94
95QStringList QskRadioBox::options() const
96{
97 return m_data->options;
98}
99
100QString QskRadioBox::optionAt( int index ) const
101{
102 return m_data->options.value( index );
103}
104
105int QskRadioBox::pressedIndex() const
106{
107 return m_data->pressedIndex;
108}
109
110void QskRadioBox::setSelectedIndex( int index )
111{
112 if( index == m_data->selectedIndex || index >= m_data->options.count() )
113 return;
114
115 if( index < 0 )
116 m_data->selectedIndex = -1;
117 else
118 m_data->selectedIndex = index;
119
120 Q_EMIT selectedIndexChanged( m_data->selectedIndex );
121}
122
123void QskRadioBox::setOptions( const QStringList& options )
124{
125 if( m_data->options == options )
126 return;
127
128 m_data->options = options;
129
130 Q_EMIT optionsChanged( options );
131 setSelectedIndex( m_data->selectedIndex );
132
133 if( m_data->focusedIndex > options.size() )
134 setFocusedIndex( options.size() - 1 );
135}
136
137void QskRadioBox::keyPressEvent( QKeyEvent* event )
138{
139 switch ( event->key() )
140 {
141 case Qt::Key_Up:
142 case Qt::Key_Left:
143 {
144 m_data->selectedIndex = qMax( m_data->selectedIndex - 1, 0 );
145 setFocusedIndex( m_data->selectedIndex );
146 update();
147
148 return;
149 }
150 case Qt::Key_Down:
151 case Qt::Key_Right:
152 {
153 m_data->selectedIndex = qMin( m_data->selectedIndex + 1,
154 m_data->options.size() - 1 );
155
156 setFocusedIndex( m_data->selectedIndex );
157 update();
158
159 return;
160 }
161 case Qt::Key_Select:
162 case Qt::Key_Return:
163 case Qt::Key_Space:
164 {
165 m_data->selectedIndex = m_data->focusedIndex;
166 update();
167
168 return;
169 }
170 }
171
172 const auto currentTabIndex = m_data->focusedIndex;
173 const auto nextTabIndex = currentTabIndex + qskFocusChainIncrement( event );
174
175 if( nextTabIndex >= m_data->options.size() || nextTabIndex < 0 )
176 {
177 Inherited::keyPressEvent( event );
178 setFocusedIndex( -1 );
179 }
180 else
181 {
182 setFocusedIndex( nextTabIndex );
183
184 const auto aspect = CheckIndicator | QskAspect::Metric | QskAspect::Position;
185 const auto hint = animationHint( aspect | skinStates() );
186
187 if( hint.isValid() )
188 startTransition( aspect, hint, currentTabIndex, nextTabIndex );
189 }
190
191 update();
192}
193
194void QskRadioBox::keyReleaseEvent( QKeyEvent* )
195{
196}
197
198void QskRadioBox::mousePressEvent( QMouseEvent* event )
199{
200 auto indexAtPosition = indexAt( qskMousePosition( event ) );
201
202 m_data->pressedIndex = indexAtPosition;
203
204 setFocusedIndex( indexAtPosition );
205 update();
206}
207
208void QskRadioBox::mouseUngrabEvent()
209{
210 if ( m_data->pressedIndex >= 0 )
211 {
212 m_data->pressedIndex = -1;
213 update();
214 }
215}
216
217void QskRadioBox::mouseReleaseEvent( QMouseEvent* event )
218{
219 const auto index = indexAt( qskMousePosition( event ) );
220 if( index == m_data->pressedIndex )
221 setSelectedIndex( index );
222
223 m_data->pressedIndex = -1;
224 update();
225}
226
227void QskRadioBox::hoverEnterEvent( QHoverEvent* event )
228{
229 const auto index = indexAt( qskHoverPosition( event ) );
230 setHoveredIndex( index );
231}
232
233void QskRadioBox::hoverMoveEvent( QHoverEvent* event )
234{
235 const auto index = indexAt( qskHoverPosition( event ) );
236 setHoveredIndex( index );
237}
238
239void QskRadioBox::hoverLeaveEvent( QHoverEvent* )
240{
241 setHoveredIndex( -1 );
242}
243
244void QskRadioBox::focusInEvent( QFocusEvent* event )
245{
246 if( event->reason() == Qt::TabFocusReason )
247 {
248 setFocusedIndex( 0 );
249 }
250 else if( event->reason() == Qt::BacktabFocusReason )
251 {
252 setFocusedIndex( m_data->options.size() - 1 );
253 }
254
255 update();
256 Inherited::focusInEvent( event );
257}
258
259void QskRadioBox::focusOutEvent( QFocusEvent* event )
260{
261 setFocusedIndex( -1 );
262 update();
263
264 Inherited::focusOutEvent( event );
265}
266
267int QskRadioBox::indexAt( const QPointF& pos ) const
268{
269 return effectiveSkinlet()->sampleIndexAt( this,
270 contentsRect(), QskRadioBox::Button, pos );
271}
272
273void QskRadioBox::setHoveredIndex( int index )
274{
275 if ( m_data->hoveredIndex == index )
276 return;
277
278 m_data->hoveredIndex = index;
279 setPositionHint( CheckIndicator | Hovered, index );
280
281 update();
282}
283
284void QskRadioBox::setFocusedIndex( int index )
285{
286 if ( m_data->focusedIndex == index )
287 return;
288
289 m_data->focusedIndex = index;
290 setPositionHint( CheckIndicator, index );
291
292 update();
293
295}
296
297#include "moc_QskRadioBox.cpp"
Lookup key for a QskSkinHintTable.
Definition QskAspect.h:15
@ FirstUserState
Definition QskAspect.h:116
void focusIndicatorRectChanged()
static const QskAspect::State Hovered
Definition QskControl.h:56
QRectF contentsRect() const
QRectF rect
Definition QskItem.h:21
QRectF focusIndicatorRect() const override
const QskSkinlet * skinlet() const
QskAnimationHint animationHint(QskAspect, QskSkinHintStatus *=nullptr) const
const QskSkinlet * effectiveSkinlet() const