refs #617, allow to use CGuiActionBindHandler with buttons

* used for weather enable/disable
* use actionBindWasDestroyed when corresponding BlackCore::CActionBind is destroyed
This commit is contained in:
Klaus Basan
2017-02-03 20:43:33 +01:00
committed by Mathew Sutcliffe
parent 1889270011
commit 74d608b5df
5 changed files with 101 additions and 31 deletions

View File

@@ -58,8 +58,11 @@ namespace BlackCore
std::function<void()> m_deleteCallback; //!< called when deleted std::function<void()> m_deleteCallback; //!< called when deleted
}; };
//! Single binding
using CActionBinding = QSharedPointer<CActionBind>;
//! List of bindings //! List of bindings
using CActionBindings = QList<QSharedPointer<CActionBind>>; using CActionBindings = QList<CActionBinding>;
} }
#endif #endif

View File

@@ -11,6 +11,7 @@
#include "blackgui/infoarea.h" #include "blackgui/infoarea.h"
#include "blackgui/views/viewbase.h" #include "blackgui/views/viewbase.h"
#include "blackgui/guiapplication.h" #include "blackgui/guiapplication.h"
#include "blackgui/guiactionbind.h"
#include "blackcore/context/contextapplication.h" #include "blackcore/context/contextapplication.h"
#include "blackcore/context/contextsimulator.h" #include "blackcore/context/contextsimulator.h"
#include "blackcore/context/contextownaircraft.h" #include "blackcore/context/contextownaircraft.h"
@@ -43,21 +44,24 @@ namespace BlackGui
ui(new Ui::CWeatherComponent) ui(new Ui::CWeatherComponent)
{ {
ui->setupUi(this); ui->setupUi(this);
m_weatherScenarios = CWeatherGrid::getAllScenarios();
for (const auto &scenario : m_weatherScenarios) m_weatherScenarios = CWeatherGrid::getAllScenarios();
for (const auto &scenario : as_const(m_weatherScenarios))
{ {
ui->cb_weatherScenario->addItem(scenario.getName(), QVariant::fromValue(scenario)); ui->cb_weatherScenario->addItem(scenario.getName(), QVariant::fromValue(scenario));
} }
auto scenario = m_weatherScenarioSetting.get();
ui->cb_weatherScenario->setCurrentIndex(scenario.getIndex());
const auto scenario = m_weatherScenarioSetting.get();
ui->cb_weatherScenario->setCurrentIndex(scenario.getIndex());
ui->pb_ActivateWeather->setIcon(CIcons::metar()); ui->pb_ActivateWeather->setIcon(CIcons::metar());
setupConnections(); setupConnections();
setupInputValidators(); setupInputValidators();
setupCompleter(); setupCompleter();
// hotkeys
m_hotkeyBindings.append(CGuiActionBindHandler::bindButton(ui->pb_ActivateWeather, "Weather/Toggle weather", true));
// Set interval to 5 min // Set interval to 5 min
m_weatherUpdateTimer.setInterval(1000 * 60 * 5); m_weatherUpdateTimer.setInterval(1000 * 60 * 5);
@@ -146,7 +150,7 @@ namespace BlackGui
{ {
Q_ASSERT(sGui->getIContextOwnAircraft()); Q_ASSERT(sGui->getIContextOwnAircraft());
position = sGui->getIContextOwnAircraft()->getOwnAircraft().getPosition(); position = sGui->getIContextOwnAircraft()->getOwnAircraft().getPosition();
if(position == CCoordinateGeodetic()) if (position == CCoordinateGeodetic())
{ {
ui->le_LatOrIcao->setText("N/A"); ui->le_LatOrIcao->setText("N/A");
ui->le_Lon->setText("N/A"); ui->le_Lon->setText("N/A");
@@ -187,7 +191,7 @@ namespace BlackGui
if (CWeatherScenario::isRealWeatherScenario(scenario)) if (CWeatherScenario::isRealWeatherScenario(scenario))
{ {
if (!useOwnAcftPosition || if (!useOwnAcftPosition ||
calculateGreatCircleDistance(position, m_lastOwnAircraftPosition).value(CLengthUnit::km()) > 20 ) calculateGreatCircleDistance(position, m_lastOwnAircraftPosition).value(CLengthUnit::km()) > 20)
{ {
requestWeatherGrid(position); requestWeatherGrid(position);
m_lastOwnAircraftPosition = position; m_lastOwnAircraftPosition = position;
@@ -201,7 +205,7 @@ namespace BlackGui
void CWeatherComponent::weatherGridReceived(const CWeatherGrid &weatherGrid, const CIdentifier &identifier) void CWeatherComponent::weatherGridReceived(const CWeatherGrid &weatherGrid, const CIdentifier &identifier)
{ {
if(!isMyIdentifier(identifier)) { return; } if (!isMyIdentifier(identifier)) { return; }
ui->lb_Status->setText({}); ui->lb_Status->setText({});
setWeatherGrid(weatherGrid); setWeatherGrid(weatherGrid);
} }

View File

@@ -12,8 +12,9 @@
#ifndef BLACKGUI_WEATHERCOMPONENT_H #ifndef BLACKGUI_WEATHERCOMPONENT_H
#define BLACKGUI_WEATHERCOMPONENT_H #define BLACKGUI_WEATHERCOMPONENT_H
#include "blackgui/blackguiexport.h"
#include "blackgui/components/enablefordockwidgetinfoarea.h" #include "blackgui/components/enablefordockwidgetinfoarea.h"
#include "blackgui/blackguiexport.h"
#include "blackcore/actionbind.h"
#include "blackmisc/geo/coordinategeodetic.h" #include "blackmisc/geo/coordinategeodetic.h"
#include "blackmisc/simulation/simulatorsettings.h" #include "blackmisc/simulation/simulatorsettings.h"
#include "blackmisc/weather/weatherscenario.h" #include "blackmisc/weather/weatherscenario.h"
@@ -77,6 +78,7 @@ namespace BlackGui
QTimer m_weatherUpdateTimer { this }; QTimer m_weatherUpdateTimer { this };
BlackMisc::Geo::CCoordinateGeodetic m_lastOwnAircraftPosition; BlackMisc::Geo::CCoordinateGeodetic m_lastOwnAircraftPosition;
BlackMisc::CSetting<BlackMisc::Simulation::TSelectedWeatherScenario> m_weatherScenarioSetting { this }; BlackMisc::CSetting<BlackMisc::Simulation::TSelectedWeatherScenario> m_weatherScenarioSetting { this };
BlackCore::CActionBindings m_hotkeyBindings;
bool m_isWeatherActivated = false; bool m_isWeatherActivated = false;
}; };
} // namespace } // namespace

View File

@@ -15,9 +15,14 @@ using namespace BlackCore;
namespace BlackGui namespace BlackGui
{ {
CGuiActionBindHandler::CGuiActionBindHandler(QAction *action) : QObject(action) CGuiActionBindHandler::CGuiActionBindHandler(QAction *action) : QObject(action), m_action(action)
{ {
this->setAction(action); this->connectDestroy(action);
}
CGuiActionBindHandler::CGuiActionBindHandler(QAbstractButton *button) : QObject(button), m_button(button)
{
this->connectDestroy(button);
} }
CGuiActionBindHandler::~CGuiActionBindHandler() CGuiActionBindHandler::~CGuiActionBindHandler()
@@ -27,6 +32,7 @@ namespace BlackGui
CActionBindings CGuiActionBindHandler::bindMenu(QMenu *menu, const QString &path) CActionBindings CGuiActionBindHandler::bindMenu(QMenu *menu, const QString &path)
{ {
Q_ASSERT(menu);
CActionBindings boundActions; CActionBindings boundActions;
if (!menu || menu->isEmpty()) { return boundActions; } if (!menu || menu->isEmpty()) { return boundActions; }
for (QAction *action : menu->actions()) for (QAction *action : menu->actions())
@@ -41,19 +47,36 @@ namespace BlackGui
} }
CGuiActionBindHandler *bindHandler = new CGuiActionBindHandler(action); CGuiActionBindHandler *bindHandler = new CGuiActionBindHandler(action);
QSharedPointer<CActionBind> actionBind(new CActionBind(pathNew, bindHandler, &CGuiActionBindHandler::boundFunction, [bindHandler]() { bindHandler->deleteLater(); })); CActionBinding actionBinding(new CActionBind(pathNew, bindHandler, &CGuiActionBindHandler::boundFunction, [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
bindHandler->m_index = actionBind->getIndex(); bindHandler->m_index = actionBinding->getIndex();
boundActions.append(actionBind); // takes ownership boundActions.append(actionBinding); // takes ownership
} }
return boundActions; return boundActions;
} }
void CGuiActionBindHandler::setAction(QAction *action) CActionBinding CGuiActionBindHandler::bindButton(QAbstractButton *button, const QString &path, bool absoluteName)
{ {
this->m_action = action; Q_ASSERT(button);
const QString pathNew = absoluteName ?
path :
CGuiActionBindHandler::appendPath(path, button->text()).remove('&'); // remove E&xit key codes
CGuiActionBindHandler *bindHandler = new CGuiActionBindHandler(button);
CActionBinding actionBinding(new CActionBind(pathNew, bindHandler, &CGuiActionBindHandler::boundFunction, [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
bindHandler->m_index = actionBinding->getIndex();
return actionBinding;
}
void CGuiActionBindHandler::actionBindWasDestroyed(CGuiActionBindHandler *bindHandler)
{
if (!bindHandler) { return; }
bindHandler->reset();
// do not delete, as it might be still referenced somewhere
}
void CGuiActionBindHandler::connectDestroy(QObject *object)
{
// if the action is destroyed from somewhere else I unbind myself // if the action is destroyed from somewhere else I unbind myself
QObject::connect(action, &QAction::destroyed, [ = ] QObject::connect(object, &QObject::destroyed, [ = ]
{ {
this->unbind(); this->unbind();
}); });
@@ -61,22 +84,40 @@ namespace BlackGui
void CGuiActionBindHandler::unbind() void CGuiActionBindHandler::unbind()
{ {
if (!this->m_action) { return; } if (this->hasTarget())
this->m_action = nullptr; {
if (CInputManager::instance()) if (CInputManager::instance())
{ {
CInputManager::instance()->unbind(this->m_index); CInputManager::instance()->unbind(this->m_index);
m_index = -1;
} }
} }
this->reset();
}
void CGuiActionBindHandler::reset()
{
m_index = -1;
m_button = nullptr;
m_action = nullptr;
}
bool CGuiActionBindHandler::hasTarget() const
{
return (m_button || m_action) && m_index >= 0;
}
void CGuiActionBindHandler::boundFunction(bool enabled) void CGuiActionBindHandler::boundFunction(bool enabled)
{ {
if (!enabled) { return; } if (!enabled || !this->hasTarget()) { return; }
if (!m_action) { return; } if (m_action)
if (m_index < 0) { return; } {
m_action->trigger(); m_action->trigger();
} }
else if (m_button)
{
m_button->click();
}
}
QString CGuiActionBindHandler::appendPath(const QString &path, const QString &name) QString CGuiActionBindHandler::appendPath(const QString &path, const QString &name)
{ {

View File

@@ -17,6 +17,8 @@
#include <QMenu> #include <QMenu>
#include <QList> #include <QList>
#include <QPushButton>
#include <QToolButton>
#include <QScopedPointer> #include <QScopedPointer>
namespace BlackGui namespace BlackGui
@@ -27,9 +29,6 @@ namespace BlackGui
Q_OBJECT Q_OBJECT
public: public:
//! Constructor
CGuiActionBindHandler(QAction *action);
//! Destructor //! Destructor
virtual ~CGuiActionBindHandler(); virtual ~CGuiActionBindHandler();
@@ -37,23 +36,44 @@ namespace BlackGui
void boundFunction(bool enabled); void boundFunction(bool enabled);
//! Bind whole menu //! Bind whole menu
//! \remark keep BlackCore::CActionBindings as long you want to keep this binding alive
static BlackCore::CActionBindings bindMenu(QMenu *menu, const QString &path = {}); static BlackCore::CActionBindings bindMenu(QMenu *menu, const QString &path = {});
//! Bind button, with relative name
//! \remark keep BlackCore::CActionBinding as long you want to keep this binding alive
static BlackCore::CActionBinding bindButton(QAbstractButton *button, const QString &path, bool absoluteName);
//! Corresponding BlackCore::CActionBind died, so delete CGuiActionBindHandler
static void actionBindWasDestroyed(CGuiActionBindHandler *bindHandler);
private: private:
//! Constructor for QAction
CGuiActionBindHandler(QAction *action);
//! Constructor for QPushButton
CGuiActionBindHandler(QAbstractButton *button);
//! Corresponding action destroyed //! Corresponding action destroyed
void destroyed(); void destroyed();
//! Set the action //! Set the action
void setAction(QAction *action); void connectDestroy(QObject *action);
//! Unbind this action //! Unbind this action
void unbind(); void unbind();
//! Reset
void reset();
//! Target available?
bool hasTarget() const;
//! Append path for action //! Append path for action
static QString appendPath(const QString &path, const QString &name); static QString appendPath(const QString &path, const QString &name);
int m_index = -1; int m_index = -1;
QAction *m_action = nullptr; QAction *m_action = nullptr;
QAbstractButton *m_button = nullptr;
}; };
} // namespace } // namespace