QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskStatusIndicator.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskStatusIndicator.h"
7#include "QskColorFilter.h"
8#include "QskGraphic.h"
9#include "QskGraphicProvider.h"
10
11#include <qdebug.h>
12
13QSK_SUBCONTROL( QskStatusIndicator, Graphic )
14
15namespace
16{
17 class StatusData
18 {
19 public:
20 StatusData( const QskGraphic& graphic )
21 : graphic( graphic )
22 , isDirty( false )
23 {
24 }
25
26 StatusData( const QUrl& url )
27 : source( url )
28 , isDirty( !url.isEmpty() )
29 {
30 }
31
32 void ensureGraphic( const QskStatusIndicator* indicator )
33 {
34 if ( !source.isEmpty() && isDirty )
35 {
36 graphic = indicator->loadSource( source );
37 isDirty = false;
38 }
39 }
40
41 QUrl source;
42 QskGraphic graphic;
43 bool isDirty : 1;
44 };
45}
46
47class QskStatusIndicator::PrivateData
48{
49 public:
50 PrivateData()
51 : currentStatus( -1 )
52 {
53 }
54
55 int currentStatus;
56 QMap< int, StatusData > map;
57 mutable QList< int > statusList;
58};
59
60QskStatusIndicator::QskStatusIndicator( QQuickItem* parent )
61 : Inherited( parent )
62 , m_data( new PrivateData() )
63{
64 initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Expanding );
65}
66
67QskStatusIndicator::~QskStatusIndicator()
68{
69}
70
71QUrl QskStatusIndicator::source( int status ) const
72{
73 const auto it = m_data->map.constFind( status );
74 if ( it != m_data->map.constEnd() )
75 return it->source;
76
77 return QUrl();
78}
79
80void QskStatusIndicator::setSource( int status, const QString& source )
81{
82 setSource( status, QUrl( source ) );
83}
84
85void QskStatusIndicator::setSource( int status, const QUrl& url )
86{
87 bool hasChanged = false;
88
89 const auto it = m_data->map.find( status );
90 if ( it != m_data->map.end() )
91 {
92 if ( it->source != url )
93 {
94 it->source = url;
95 it->graphic.reset();
96 it->isDirty = !url.isEmpty();
97
98 hasChanged = true;
99 }
100 }
101 else
102 {
103 m_data->map.insert( status, StatusData( url ) );
104 m_data->statusList.clear();
105
106 hasChanged = true;
107 }
108
109 if ( hasChanged )
110 {
112
113 if ( status == m_data->currentStatus )
114 update();
115 }
116}
117
118QskGraphic QskStatusIndicator::graphic( int status ) const
119{
120 const auto it = m_data->map.find( status );
121 if ( it != m_data->map.end() )
122 {
123 it->ensureGraphic( this );
124 return it->graphic;
125 }
126
127 return QskGraphic();
128}
129
130void QskStatusIndicator::setGraphic( int status, const QskGraphic& graphic )
131{
132 bool hasChanged = false;
133
134 const auto it = m_data->map.find( status );
135 if ( it != m_data->map.end() )
136 {
137 if ( !it->source.isEmpty() || graphic != it->graphic )
138 {
139 it->source.clear();
140 it->isDirty = false;
141 it->graphic = graphic;
142
143 hasChanged = true;
144 }
145 }
146 else
147 {
148 m_data->map.insert( status, StatusData( graphic ) );
149 m_data->statusList.clear();
150 hasChanged = true;
151 }
152
153 if ( hasChanged )
154 {
156
157 if ( status == m_data->currentStatus )
158 update();
159 }
160}
161
162QskColorFilter QskStatusIndicator::graphicFilter( int status ) const
163{
164 Q_UNUSED( status )
165 return effectiveGraphicFilter( Graphic );
166}
167
168void QskStatusIndicator::setGraphicRole( int role )
169{
170 if ( setGraphicRoleHint( Graphic, role ) )
171 Q_EMIT graphicRoleChanged( role );
172}
173
174void QskStatusIndicator::resetGraphicRole()
175{
176 if ( resetGraphicRoleHint( Graphic ) )
177 Q_EMIT graphicRoleChanged( graphicRoleHint( Graphic ) );
178}
179
180int QskStatusIndicator::graphicRole() const
181{
182 return graphicRoleHint( Graphic );
183}
184
185int QskStatusIndicator::status() const
186{
187 return m_data->currentStatus;
188}
189
190bool QskStatusIndicator::hasStatus( int status ) const
191{
192 return m_data->map.contains( status );
193}
194
195void QskStatusIndicator::setStatus( int status )
196{
197 if ( status == m_data->currentStatus )
198 return;
199
200 const auto it = m_data->map.constFind( status );
201 if ( it == m_data->map.constEnd() )
202 {
203 qWarning() << "QskStatusIndicator: invalid status:" << status;
204 return;
205 }
206
207 m_data->currentStatus = status;
208 Q_EMIT statusChanged( m_data->currentStatus );
209
210 // we should have a mode to decide if we
211 // want to keep the hidden graphics in memory
212
213 if ( it->isDirty )
214 polish();
215
216 update();
217}
218
219QList< int > QskStatusIndicator::statusList() const
220{
221 /*
222 We should be have a QMap< int, QskGraphic >, so that
223 users can iterate over all entries without having to
224 do extra lookups for each entry. TODO ...
225 */
226 if ( m_data->statusList.isEmpty() && !m_data->map.isEmpty() )
227 m_data->statusList = m_data->map.keys();
228
229 return m_data->statusList;
230}
231
233{
234 if ( event->type() == QEvent::StyleChange )
235 {
236 for ( auto& statusData : m_data->map )
237 {
238 if ( !statusData.source.isEmpty() )
239 {
240 statusData.graphic.reset();
241 statusData.isDirty = true;
242 }
243 }
244 }
245
246 Inherited::changeEvent( event );
247}
248
249void QskStatusIndicator::updateLayout()
250{
251 const auto it = m_data->map.find( m_data->currentStatus );
252 if ( it != m_data->map.end() )
253 it->ensureGraphic( this );
254}
255
256QskGraphic QskStatusIndicator::loadSource( const QUrl& url ) const
257{
258 return Qsk::loadGraphic( url );
259}
260
261#include "moc_QskStatusIndicator.cpp"
A paint device for scalable graphics.
Definition QskGraphic.h:28
void resetImplicitSize()
Definition QskItem.cpp:721
virtual void changeEvent(QEvent *)
Definition QskItem.cpp:859
bool resetGraphicRoleHint(QskAspect)
Removes a graphic role hint from the local table.
bool setGraphicRoleHint(QskAspect, int role)
Sets a graphic role hint.
int graphicRoleHint(QskAspect, QskSkinHintStatus *=nullptr) const
A Retrieves a graphic role hint.
QskColorFilter effectiveGraphicFilter(QskAspect::Subcontrol) const
void changeEvent(QEvent *) override