qskinny/src/controls/QskStatusIndicator.cpp

257 lines
5.6 KiB
C++
Raw Normal View History

2017-07-21 18:21:34 +02:00
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskStatusIndicator.h"
#include "QskColorFilter.h"
2018-08-03 08:15:28 +02:00
#include "QskGraphic.h"
2017-07-21 18:21:34 +02:00
#include "QskGraphicProvider.h"
2018-07-19 14:10:48 +02:00
#include <qdebug.h>
2017-07-21 18:21:34 +02:00
QSK_SUBCONTROL( QskStatusIndicator, Graphic )
namespace
{
class StatusData
{
2018-08-03 08:15:28 +02:00
public:
StatusData( const QskGraphic& graphic )
: graphic( graphic )
, isDirty( false )
2017-07-21 18:21:34 +02:00
{
}
2018-08-03 08:15:28 +02:00
StatusData( const QUrl& url )
: source( url )
, isDirty( !url.isEmpty() )
2017-07-21 18:21:34 +02:00
{
}
void ensureGraphic( const QskStatusIndicator* indicator )
{
if ( !source.isEmpty() && isDirty )
{
graphic = indicator->loadSource( source );
isDirty = false;
}
}
QUrl source;
QskGraphic graphic;
bool isDirty : 1;
};
}
class QskStatusIndicator::PrivateData
{
2018-08-03 08:15:28 +02:00
public:
PrivateData()
: currentStatus( -1 )
2017-07-21 18:21:34 +02:00
{
}
int currentStatus;
QMap< int, StatusData > map;
2020-12-29 10:11:31 +01:00
mutable QList<int> statusList;
2017-07-21 18:21:34 +02:00
};
2018-08-03 08:15:28 +02:00
QskStatusIndicator::QskStatusIndicator( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData() )
2017-07-21 18:21:34 +02:00
{
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Expanding );
2017-07-21 18:21:34 +02:00
}
QskStatusIndicator::~QskStatusIndicator()
{
}
QUrl QskStatusIndicator::source( int status ) const
{
2020-12-29 10:11:31 +01:00
const auto it = m_data->map.constFind( status );
if ( it != m_data->map.constEnd() )
2017-07-21 18:21:34 +02:00
return it->source;
return QUrl();
}
void QskStatusIndicator::setSource( int status, const QUrl& url )
{
bool hasChanged = false;
const auto it = m_data->map.find( status );
if ( it != m_data->map.end() )
{
if ( it->source != url )
{
it->source = url;
it->graphic.reset();
it->isDirty = !url.isEmpty();
hasChanged = true;
}
}
else
{
m_data->map.insert( status, StatusData( url ) );
2020-12-29 10:11:31 +01:00
m_data->statusList.clear();
2017-07-21 18:21:34 +02:00
hasChanged = true;
}
if ( hasChanged )
{
resetImplicitSize();
if ( status == m_data->currentStatus )
update();
}
}
QskGraphic QskStatusIndicator::graphic( int status ) const
{
const auto it = m_data->map.find( status );
if ( it != m_data->map.end() )
2020-12-29 10:11:31 +01:00
{
it->ensureGraphic( this );
2017-07-21 18:21:34 +02:00
return it->graphic;
2020-12-29 10:11:31 +01:00
}
2017-07-21 18:21:34 +02:00
return QskGraphic();
}
void QskStatusIndicator::setGraphic( int status, const QskGraphic& graphic )
{
bool hasChanged = false;
const auto it = m_data->map.find( status );
if ( it != m_data->map.end() )
{
if ( !it->source.isEmpty() || graphic != it->graphic )
{
it->source.clear();
it->isDirty = false;
it->graphic = graphic;
hasChanged = true;
}
}
else
{
m_data->map.insert( status, StatusData( graphic ) );
2020-12-29 10:11:31 +01:00
m_data->statusList.clear();
2017-07-21 18:21:34 +02:00
hasChanged = true;
}
if ( hasChanged )
{
resetImplicitSize();
if ( status == m_data->currentStatus )
update();
}
}
QskColorFilter QskStatusIndicator::graphicFilter( int status ) const
{
Q_UNUSED( status )
2021-01-07 13:49:57 +01:00
return effectiveGraphicFilter( Graphic );
}
void QskStatusIndicator::setGraphicRole( int role )
{
if ( setGraphicRoleHint( Graphic, role ) )
Q_EMIT graphicRoleChanged( role );
}
void QskStatusIndicator::resetGraphicRole()
{
if ( resetGraphicRoleHint( Graphic ) )
Q_EMIT graphicRoleChanged( graphicRoleHint( Graphic ) );
}
int QskStatusIndicator::graphicRole() const
{
return graphicRoleHint( Graphic );
2017-07-21 18:21:34 +02:00
}
int QskStatusIndicator::status() const
{
return m_data->currentStatus;
}
bool QskStatusIndicator::hasStatus( int status ) const
{
return m_data->map.contains( status );
}
void QskStatusIndicator::setStatus( int status )
{
if ( status == m_data->currentStatus )
return;
2017-10-29 14:01:06 +01:00
const auto it = m_data->map.constFind( status );
2017-07-21 18:21:34 +02:00
if ( it == m_data->map.constEnd() )
{
qWarning() << "QskStatusIndicator: invalid status:" << status;
return;
}
m_data->currentStatus = status;
Q_EMIT statusChanged( m_data->currentStatus );
// we should have a mode to decide if we
// want to keep the hidden graphics in memory
if ( it->isDirty )
polish();
update();
}
2020-12-29 10:11:31 +01:00
QList<int> QskStatusIndicator::statusList() const
{
/*
We should be have a QMap< int, QskGraphic >, so that
users can iterate over all entries without having to
do extra lookups for each entry. TODO ...
*/
if ( m_data->statusList.isEmpty() && !m_data->map.isEmpty() )
m_data->statusList = m_data->map.keys();
return m_data->statusList;
}
2017-07-21 18:21:34 +02:00
void QskStatusIndicator::changeEvent( QEvent* event )
{
if ( event->type() == QEvent::StyleChange )
{
2018-08-03 08:15:28 +02:00
for ( auto& statusData : m_data->map )
2017-07-21 18:21:34 +02:00
{
if ( !statusData.source.isEmpty() )
{
statusData.graphic.reset();
statusData.isDirty = true;
}
}
}
Inherited::changeEvent( event );
}
void QskStatusIndicator::updateLayout()
{
const auto it = m_data->map.find( m_data->currentStatus );
if ( it != m_data->map.end() )
it->ensureGraphic( this );
}
QskGraphic QskStatusIndicator::loadSource( const QUrl& url ) const
{
return Qsk::loadGraphic( url );
}
#include "moc_QskStatusIndicator.cpp"