class AbstractCommand : public QObject
{
Q_OBJECT
public:
explicit AbstractCommand(QObject* a_parent = nullptr);
Q_INVOKABLE virtual void execute() = 0;
virtual bool canExecute() const = 0;
signals:
void canExecuteChanged( bool a_canExecute );
};
AbstractCommand::AbstractCommand(QObject *a_parent)
: QObject( a_parent )
{
}
AbstractConfigurableCommand::AbstractConfigurableCommand(QObject *a_parent)
: AbstractCommand( a_parent )
, m_canExecute( false ) { }
bool AbstractConfigurableCommand::canExecute() const
{
return m_canExecute;
}
void AbstractConfigurableCommand::setCanExecute( bool a_canExecute )
{
if( a_canExecute != m_canExecute ) {
m_canExecute = a_canExecute;
emit canExecuteChanged( m_canExecute );
emit localCanExecuteChanged( m_canExecute );
}
}
#include
#include "CompositeCommand.h"
/*! \brief Constructor for a empty initial composite command */
CompositeCommand::CompositeCommand( QObject *a_parent )
: AbstractCommand ( a_parent ) {}
/*! \brief Constructor for a list of members */
CompositeCommand::CompositeCommand( QList a_members, QObject *a_parent )
: AbstractCommand ( a_parent )
{
foreach (AbstractCommand* member, a_members) {
registration(member);
m_members.append( QSharedPointer(member) );
}
}
/*! \brief Constructor for a list of members */
CompositeCommand::CompositeCommand( QList> a_members, QObject *a_parent )
: AbstractCommand ( a_parent )
, m_members ( a_members )
{
foreach (const QSharedPointer& member, m_members) {
registration(member.data());
}
}
/*! \brief Destructor */
CompositeCommand::~CompositeCommand()
{
foreach (const QSharedPointer& member, m_members) {
deregistration(member.data());
}
}
void CompositeCommand::executeAsync()
{
foreach (const QSharedPointer& member, m_members) {
member->executeAsync();
}
}
bool CompositeCommand::canExecute() const
{
foreach (const QSharedPointer& member, m_members) {
if (!member->canExecute()) {
return false;
}
}
return true;
}
/*! \brief When one's canExecute changes */
void CompositeCommand::onCanExecuteChanged( bool a_canExecute )
{
bool oldstate = !a_canExecute;
bool newstate = a_canExecute;
foreach (const QSharedPointer& member, m_members) {
if ( member.data() != sender() ) {
oldstate &= member->canExecute();
newstate &= member->canExecute();
}
}
if (oldstate != newstate) {
emit canExecuteChanged( newstate );
}
}
/*! \brief When one's execution completes */
void CompositeCommand::onExecutionCompleted( )
{
m_completedCount++;
if ( m_completedCount == m_members.count( ) ) {
m_completedCount = 0;
emit executionCompleted();
}
}
void CompositeCommand::registration( AbstractCommand* a_member )
{
connect( a_member, &AbstractCommand::canExecuteChanged,
this, &CompositeCommand::onCanExecuteChanged );
connect( a_member, &AbstractCommand::executionCompleted,
this, &CompositeCommand::onExecutionCompleted );
}
void CompositeCommand::deregistration( AbstractCommand* a_member )
{
disconnect( a_member, &AbstractCommand::canExecuteChanged,
this, &CompositeCommand::onCanExecuteChanged );
disconnect( a_member, &AbstractCommand::executionCompleted,
this, &CompositeCommand::onExecutionCompleted );
}
void CompositeCommand::handleCanExecuteChanged(bool a_oldCanExecute)
{
bool newCanExecute = canExecute();
if( a_oldCanExecute != newCanExecute )
{
emit canExecuteChanged( newCanExecute );
}
}
void CompositeCommand::add(AbstractCommand* a_member)
{
bool oldCanExecute = canExecute();
QQmlEngine::setObjectOwnership ( a_member, QQmlEngine::CppOwnership );
m_members.append( QSharedPointer( a_member ) );
registration ( a_member );
handleCanExecuteChanged(oldCanExecute);
}
void CompositeCommand::add(const QSharedPointer& a_member)
{
bool oldCanExecute = canExecute();
m_members.append( a_member );
registration ( a_member.data() );
handleCanExecuteChanged(oldCanExecute);
}
void CompositeCommand::remove(AbstractCommand* a_member)
{
bool oldCanExecute = canExecute();
QMutableListIterator > i( m_members );
while (i.hasNext()) {
QSharedPointer val = i.next();
if ( val.data() == a_member) {
deregistration(val.data());
i.remove();
}
}
handleCanExecuteChanged(oldCanExecute);
}
void CompositeCommand::remove(const QSharedPointer& a_member)
{
bool oldCanExecute = canExecute();
deregistration(a_member.data());
m_members.removeAll( a_member );
handleCanExecuteChanged(oldCanExecute);
}