QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskGraphicLabel.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskGraphicLabel.h"
7#include "QskAspect.h"
8#include "QskColorFilter.h"
9#include "QskGraphic.h"
10#include "QskGraphicProvider.h"
11#include "QskSkinManager.h"
12#include "QskSkin.h"
13#include "QskEvent.h"
14
15QSK_SUBCONTROL( QskGraphicLabel, Panel )
16QSK_SUBCONTROL( QskGraphicLabel, Graphic )
17
18class QskGraphicLabel::PrivateData
19{
20 public:
21 PrivateData( const QUrl& sourceUrl )
22 : source( sourceUrl )
23 , fillMode( QskGraphicLabel::PreserveAspectFit )
24 , mirror( false )
25 , isSourceDirty( !sourceUrl.isEmpty() )
26 , hasPanel( false )
27 {
28 }
29
30 QUrl source;
31 QskGraphic graphic;
32
33 uint fillMode : 2;
34 bool mirror : 1;
35 bool isSourceDirty : 1;
36 bool hasPanel : 1;
37};
38
39QskGraphicLabel::QskGraphicLabel( const QUrl& source, QQuickItem* parent )
40 : Inherited( parent )
41 , m_data( new PrivateData( source ) )
42{
43 initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Expanding );
44
45 if ( !m_data->source.isEmpty() )
46 polish();
47}
48
49QskGraphicLabel::QskGraphicLabel( QQuickItem* parent )
50 : QskGraphicLabel( QUrl(), parent )
51{
52}
53
54QskGraphicLabel::QskGraphicLabel( const QString& source, QQuickItem* parent )
55 : QskGraphicLabel( QUrl( source ), parent )
56{
57}
58
59QskGraphicLabel::QskGraphicLabel( const QskGraphic& graphic, QQuickItem* parent )
60 : QskGraphicLabel( parent )
61{
62 m_data->graphic = graphic;
63}
64
65QskGraphicLabel::~QskGraphicLabel()
66{
67}
68
69void QskGraphicLabel::setPanel( bool on )
70{
71 if ( on == m_data->hasPanel )
72 return;
73
74 m_data->hasPanel = on;
75
77 update();
78
79 Q_EMIT panelChanged( on );
80}
81
82bool QskGraphicLabel::hasPanel() const
83{
84 return m_data->hasPanel;
85}
86
87bool QskGraphicLabel::isEmpty() const
88{
89 return m_data->graphic.isNull() && m_data->source.isEmpty();
90}
91
92QUrl QskGraphicLabel::source() const
93{
94 return m_data->source;
95}
96
97void QskGraphicLabel::setSource( const QString& source )
98{
99 setSource( QUrl( source ) );
100}
101
102void QskGraphicLabel::setSource( const QUrl& url )
103{
104 if ( url == m_data->source )
105 return;
106
107 m_data->graphic.reset();
108 m_data->isSourceDirty = true;
109 m_data->source = url;
110
112 polish();
113 update();
114
115 Q_EMIT sourceChanged();
116}
117
118QskGraphic QskGraphicLabel::graphic() const
119{
120 return m_data->graphic;
121}
122
123void QskGraphicLabel::setGraphic( const QskGraphic& graphic )
124{
125 if ( m_data->graphic != graphic )
126 {
127 const bool keepImplicitSize = graphicStrutSize().isValid()
128 || ( m_data->graphic.defaultSize() == graphic.defaultSize() );
129
130 m_data->graphic = graphic;
131
132 if ( !keepImplicitSize )
134
135 update();
136 }
137
138 // in case we have a sequence setting a source and a graphic later
139 m_data->isSourceDirty = false;
140
141 if ( !m_data->source.isEmpty() )
142 {
143 m_data->source.clear();
144 Q_EMIT sourceChanged();
145 }
146}
147
148void QskGraphicLabel::setGraphicRole( int role )
149{
150 if ( setGraphicRoleHint( Graphic, role ) )
151 Q_EMIT graphicRoleChanged( role );
152}
153
154void QskGraphicLabel::resetGraphicRole()
155{
156 if ( resetGraphicRoleHint( Graphic ) )
157 Q_EMIT graphicRoleChanged( graphicRoleHint( Graphic ) );
158}
159
160int QskGraphicLabel::graphicRole() const
161{
162 return graphicRoleHint( Graphic );
163}
164
165QskColorFilter QskGraphicLabel::graphicFilter() const
166{
167 // can be removed once we can store a filter inidividually
168 // for a skinnable
169
170 return effectiveGraphicFilter( QskGraphicLabel::Graphic );
171}
172
173void QskGraphicLabel::setMirror( bool on )
174{
175 if ( on != m_data->mirror )
176 {
177 m_data->mirror = on;
178
179 if ( !( graphicStrutSize().isEmpty() || m_data->graphic.isEmpty() ) )
180 update();
181
182 Q_EMIT mirrorChanged();
183 }
184}
185
186bool QskGraphicLabel::mirror() const
187{
188 return m_data->mirror;
189}
190
191void QskGraphicLabel::setGraphicStrutSize( const QSizeF& size )
192{
193 auto newSize = size;
194 if ( newSize.width() < 0.0 )
195 newSize.setWidth( -1.0 );
196
197 if ( newSize.height() < 0.0 )
198 newSize.setHeight( -1.0 );
199
200 if ( setStrutSizeHint( Graphic, newSize ) )
201 Q_EMIT graphicStrutSizeChanged();
202}
203
204QSizeF QskGraphicLabel::graphicStrutSize() const
205{
206 return strutSizeHint( Graphic );
207}
208
209void QskGraphicLabel::resetGraphicStrutSize()
210{
211 if ( resetStrutSizeHint( Graphic ) )
212 Q_EMIT graphicStrutSizeChanged();
213}
214
215void QskGraphicLabel::setFillMode( FillMode mode )
216{
217 if ( mode != m_data->fillMode )
218 {
219 m_data->fillMode = mode;
220
221 if ( !m_data->graphic.isEmpty() )
222 update();
223
224 Q_EMIT fillModeChanged( mode );
225 }
226}
227
228QskGraphicLabel::FillMode QskGraphicLabel::fillMode() const
229{
230 return static_cast< QskGraphicLabel::FillMode >( m_data->fillMode );
231}
232
233void QskGraphicLabel::setAlignment( Qt::Alignment alignment )
234{
235 if ( setAlignmentHint( Graphic, alignment ) )
236 Q_EMIT alignmentChanged( alignment );
237}
238
239void QskGraphicLabel::resetAlignment()
240{
241 if ( resetAlignmentHint( Graphic ) )
242 Q_EMIT alignmentChanged( alignment() );
243}
244
245Qt::Alignment QskGraphicLabel::alignment() const
246{
247 return alignmentHint( Graphic, Qt::AlignLeft | Qt::AlignVCenter );
248}
249
250QskGraphic QskGraphicLabel::loadSource( const QUrl& url ) const
251{
252 return Qsk::loadGraphic( url );
253}
254
255void QskGraphicLabel::updateResources()
256{
257 if ( !m_data->source.isEmpty() && m_data->isSourceDirty )
258 m_data->graphic = loadSource( m_data->source );
259
260 m_data->isSourceDirty = false;
261}
262
263QSizeF QskGraphicLabel::effectiveSourceSize() const
264{
265 const auto strutSize = graphicStrutSize();
266
267 if ( strutSize.width() >= 0 && strutSize.height() >= 0 )
268 {
269 // the size has been explicitly set
270 return strutSize;
271 }
272
273 if ( !m_data->source.isEmpty() && m_data->isSourceDirty )
274 {
275 // we have to load to know about the geometry
276 m_data->graphic = loadSource( m_data->source );
277 m_data->isSourceDirty = false;
278 }
279
280 QSizeF sz( 0, 0 );
281 if ( !m_data->graphic.isEmpty() )
282 {
283 const QSizeF defaultSize = m_data->graphic.defaultSize();
284
285 if ( strutSize.width() <= 0 && strutSize.height() <= 0 )
286 {
287 // size is derived from the default size
288 sz = defaultSize;
289 }
290 else if ( strutSize.width() <= 0 )
291 {
292 // only the height has been given
293 const qreal f = strutSize.height() / defaultSize.height();
294 sz.setWidth( f * defaultSize.width() );
295 sz.setHeight( strutSize.height() );
296 }
297 else
298 {
299 // only the width has been given
300 const qreal f = strutSize.width() / defaultSize.width();
301 sz.setWidth( strutSize.width() );
302 sz.setHeight( f * defaultSize.height() );
303 }
304 }
305
306 return sz;
307}
308
310{
311 /*
312 textures will finally be scaled into a target rectangle in integer
313 coordinates. This rectangle might have a different size - depending
314 on how its coordinates are rounded ( ceiled/floored ) - even if
315 the site in floating point coordinates is the same.
316
317 So we always trigger updates - even for translations.
318
319 Note that an update triggers the checks, that are needed to decide if
320 the texture needs to be recreated - it does not necessarily
321 result in actually doing it.
322 */
323 update();
324
326}
327
328void QskGraphicLabel::changeEvent( QEvent* event )
329{
330 if ( event->type() == QEvent::StyleChange )
331 {
332 if ( !m_data->source.isEmpty() && qskSkinManager->skin()->hasGraphicProvider() )
333 {
334 // we might need to reload from a different skin
335 m_data->isSourceDirty = true;
336 }
337 }
338
339 Inherited::changeEvent( event );
340}
341
342#include "moc_QskGraphicLabel.cpp"
void geometryChangeEvent(QskGeometryChangeEvent *) override
void changeEvent(QEvent *) override
A paint device for scalable graphics.
Definition QskGraphic.h:28
void resetImplicitSize()
Definition QskItem.cpp:721
virtual void geometryChangeEvent(QskGeometryChangeEvent *)
Definition QskItem.cpp:855
virtual void changeEvent(QEvent *)
Definition QskItem.cpp:859
bool resetGraphicRoleHint(QskAspect)
Removes a graphic role hint from the local table.
bool setAlignmentHint(QskAspect, Qt::Alignment)
Sets an alignment hint.
bool setStrutSizeHint(QskAspect, const QSizeF &)
Sets a metric hint.
QSizeF strutSizeHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a strut size hint.
bool setGraphicRoleHint(QskAspect, int role)
Sets a graphic role hint.
int graphicRoleHint(QskAspect, QskSkinHintStatus *=nullptr) const
A Retrieves a graphic role hint.
bool resetAlignmentHint(QskAspect)
Removes an alignment hint from the local table.
bool resetStrutSizeHint(QskAspect)
Removes a strut size hint from the local table.
QskColorFilter effectiveGraphicFilter(QskAspect::Subcontrol) const
Qt::Alignment alignmentHint(QskAspect, Qt::Alignment=Qt::Alignment()) const
Retrieves an alignment hint.