refs #617, CActionItem supports icon

* standard paths for applications
* support for Qt::DecorationRole
* QMap<QString, QPixmap> m_availableActions
* Constructor for icon only
* only leafs support actions
This commit is contained in:
Klaus Basan
2017-02-05 03:19:25 +01:00
committed by Mathew Sutcliffe
parent 6a96d14baa
commit a34be02e07
12 changed files with 120 additions and 44 deletions

View File

@@ -11,6 +11,20 @@
namespace BlackCore namespace BlackCore
{ {
CActionBind::CActionBind(const QString &action, const QPixmap &icon)
{
CActionBind::registerAction(action, icon);
}
QString CActionBind::registerAction(const QString &action, const QPixmap &icon)
{
const QString a = CActionBind::normalizeAction(action);
auto inputManger = CInputManager::instance();
Q_ASSERT_X(inputManger, Q_FUNC_INFO, "Missing input manager");
inputManger->registerAction(a, icon);
return a;
}
CActionBind::~CActionBind() CActionBind::~CActionBind()
{ {
unbind(); unbind();
@@ -31,7 +45,8 @@ namespace BlackCore
QString CActionBind::normalizeAction(const QString &action) QString CActionBind::normalizeAction(const QString &action)
{ {
QString n = action.trimmed(); QString n = action.trimmed();
if (!n.startsWith('/')) { return n.insert(0, QChar('/')); } if (!n.startsWith('/')) { n.insert(0, QChar('/')); }
if (n.endsWith('/')) { n.remove(n.length() - 1 , 1);}
return n; return n;
} }
} }

View File

@@ -14,6 +14,7 @@
#include "blackcore/inputmanager.h" #include "blackcore/inputmanager.h"
#include "blackcoreexport.h" #include "blackcoreexport.h"
#include <QPixmap>
namespace BlackCore namespace BlackCore
{ {
@@ -29,15 +30,18 @@ namespace BlackCore
//! Constructor //! Constructor
template <typename Receiver> template <typename Receiver>
CActionBind(const QString &action, Receiver *receiver, MembFunc<Receiver> slot = nullptr, const std::function<void()> &deleteCallback = {}) : CActionBind(const QString &action, const QPixmap &icon, Receiver *receiver,
MembFunc<Receiver> slot = nullptr,
const std::function<void()> &deleteCallback = {}) :
m_deleteCallback(deleteCallback) m_deleteCallback(deleteCallback)
{ {
const QString a = CActionBind::normalizeAction(action); const QString a = CActionBind::registerAction(action, icon);
auto inputManger = CInputManager::instance(); m_index = CInputManager::instance()->bind(a, receiver, slot);
inputManger->registerAction(a);
m_index = inputManger->bind(a, receiver, slot);
} }
//! Signature just to set an icon for an action
CActionBind(const QString &action, const QPixmap &icon);
//! Destructor //! Destructor
~CActionBind(); ~CActionBind();
@@ -51,9 +55,12 @@ namespace BlackCore
int getIndex() const { return m_index; } int getIndex() const { return m_index; }
private: private:
//! normalize the name string //! Normalize the action string
static QString normalizeAction(const QString &action); static QString normalizeAction(const QString &action);
//! Register action
static QString registerAction(const QString &action, const QPixmap &icon);
int m_index = -1; //!< action indexx (unique) int m_index = -1; //!< action indexx (unique)
std::function<void()> m_deleteCallback; //!< called when deleted std::function<void()> m_deleteCallback; //!< called when deleted
}; };

View File

@@ -37,11 +37,11 @@ namespace BlackCore
return &instance; return &instance;
} }
void CInputManager::registerAction(const QString &action) void CInputManager::registerAction(const QString &action, const QPixmap &icon)
{ {
if (!m_availableActions.contains(action)) if (!m_availableActions.contains(action))
{ {
m_availableActions.push_back(action); m_availableActions.insert(action, icon);
emit hotkeyActionRegistered({ action }); emit hotkeyActionRegistered({ action });
} }
} }
@@ -52,7 +52,7 @@ namespace BlackCore
{ {
if (!m_availableActions.contains(action)) if (!m_availableActions.contains(action))
{ {
m_availableActions.push_back(action); m_availableActions.insert(action, {});
emit hotkeyActionRegistered({ action }); emit hotkeyActionRegistered({ action });
} }
} }

View File

@@ -18,6 +18,7 @@
#include "blackinput/keyboard.h" #include "blackinput/keyboard.h"
#include "blackmisc/input/hotkeycombination.h" #include "blackmisc/input/hotkeycombination.h"
#include "blackmisc/settingscache.h" #include "blackmisc/settingscache.h"
#include "blackmisc/icons.h"
#include <QHash> #include <QHash>
#include <QObject> #include <QObject>
@@ -38,7 +39,7 @@ namespace BlackCore
public: public:
//! Register new action //! Register new action
void registerAction(const QString &action); void registerAction(const QString &action, const QPixmap &icon = BlackMisc::CIcons::empty16());
//! Register remote actions //! Register remote actions
void registerRemoteActions(const QStringList &actions); void registerRemoteActions(const QStringList &actions);
@@ -72,7 +73,10 @@ namespace BlackCore
void resetAllActions() { m_configuredActions.clear(); } void resetAllActions() { m_configuredActions.clear(); }
//! Get all available and known actions //! Get all available and known actions
QStringList allAvailableActions() const { return m_availableActions; } QStringList allAvailableActions() const { return m_availableActions.keys(); }
//! All actions and their icons (if any)
QMap<QString, QPixmap> allAvailableActionsAndIcons() const { return m_availableActions; }
//! Enable event forwarding to core //! Enable event forwarding to core
void setForwarding(bool enabled) { m_actionRelayingEnabled = enabled; } void setForwarding(bool enabled) { m_actionRelayingEnabled = enabled; }
@@ -129,7 +133,7 @@ namespace BlackCore
std::unique_ptr<BlackInput::IKeyboard> m_keyboard; std::unique_ptr<BlackInput::IKeyboard> m_keyboard;
std::unique_ptr<BlackInput::IJoystick> m_joystick; std::unique_ptr<BlackInput::IJoystick> m_joystick;
QStringList m_availableActions; QMap<QString, QPixmap> m_availableActions;
QHash<BlackMisc::Input::CHotkeyCombination, QString> m_configuredActions; QHash<BlackMisc::Input::CHotkeyCombination, QString> m_configuredActions;
QVector<BindInfo> m_boundActions; QVector<BindInfo> m_boundActions;
@@ -142,4 +146,4 @@ namespace BlackCore
}; };
} }
#endif //BLACKCORE_INPUTMANAGER_H #endif //guard

View File

@@ -19,6 +19,7 @@
#include "blackmisc/input/actionhotkey.h" #include "blackmisc/input/actionhotkey.h"
#include "blackmisc/input/actionhotkeylist.h" #include "blackmisc/input/actionhotkeylist.h"
#include "blackmisc/settingscache.h" #include "blackmisc/settingscache.h"
#include "blackmisc/icons.h"
#include <QFrame> #include <QFrame>
#include <QObject> #include <QObject>
@@ -60,7 +61,7 @@ namespace BlackGui
QScopedPointer<Ui::CSettingsHotkeyComponent> ui; QScopedPointer<Ui::CSettingsHotkeyComponent> ui;
BlackGui::Models::CActionHotkeyListModel m_model; BlackGui::Models::CActionHotkeyListModel m_model;
BlackMisc::CSetting<BlackCore::Application::TActionHotkeys> m_actionHotkeys { this }; BlackMisc::CSetting<BlackCore::Application::TActionHotkeys> m_actionHotkeys { this };
BlackCore::CActionBind m_action { "/Test/Message", this, &CSettingsHotkeyComponent::ps_hotkeySlot }; BlackCore::CActionBind m_action { "/Test/Message", BlackMisc::CIcons::wrench16(), this, &CSettingsHotkeyComponent::ps_hotkeySlot };
}; };
} // ns } // ns
} // ns } // ns

View File

@@ -60,7 +60,8 @@ namespace BlackGui
setupCompleter(); setupCompleter();
// hotkeys // hotkeys
m_hotkeyBindings.append(CGuiActionBindHandler::bindButton(ui->pb_ActivateWeather, "Weather/Toggle weather", true)); const QString swift(CGuiActionBindHandler::pathSwiftPilotClient());
m_hotkeyBindings.append(CGuiActionBindHandler::bindButton(ui->pb_ActivateWeather, swift + "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);

View File

@@ -9,6 +9,7 @@
#include "guiactionbind.h" #include "guiactionbind.h"
#include "blackmisc/fileutils.h" #include "blackmisc/fileutils.h"
#include "blackmisc/imageutils.h"
using namespace BlackMisc; using namespace BlackMisc;
using namespace BlackCore; using namespace BlackCore;
@@ -46,8 +47,9 @@ namespace BlackGui
CGuiActionBindHandler::bindMenu(action->menu(), pathNew); CGuiActionBindHandler::bindMenu(action->menu(), pathNew);
} }
const bool hasIcon = !action->icon().isNull();
CGuiActionBindHandler *bindHandler = new CGuiActionBindHandler(action); CGuiActionBindHandler *bindHandler = new CGuiActionBindHandler(action);
CActionBinding actionBinding(new CActionBind(pathNew, bindHandler, &CGuiActionBindHandler::boundFunction, [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); })); CActionBinding actionBinding(new CActionBind(pathNew, hasIcon ? action->icon().pixmap(CIcons::empty16().size()) : CIcons::empty16(), bindHandler, &CGuiActionBindHandler::boundFunction, [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
bindHandler->m_index = actionBinding->getIndex(); bindHandler->m_index = actionBinding->getIndex();
boundActions.append(actionBinding); // takes ownership boundActions.append(actionBinding); // takes ownership
} }
@@ -61,7 +63,8 @@ namespace BlackGui
path : path :
CGuiActionBindHandler::appendPath(path, button->text()).remove('&'); // remove E&xit key codes CGuiActionBindHandler::appendPath(path, button->text()).remove('&'); // remove E&xit key codes
CGuiActionBindHandler *bindHandler = new CGuiActionBindHandler(button); CGuiActionBindHandler *bindHandler = new CGuiActionBindHandler(button);
CActionBinding actionBinding(new CActionBind(pathNew, bindHandler, &CGuiActionBindHandler::boundFunction, [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); })); const bool hasIcon = !button->icon().isNull();
CActionBinding actionBinding(new CActionBind(pathNew, hasIcon ? button->icon().pixmap(CIcons::empty16().size()) : CIcons::empty16(), bindHandler, &CGuiActionBindHandler::boundFunction, [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
bindHandler->m_index = actionBinding->getIndex(); bindHandler->m_index = actionBinding->getIndex();
return actionBinding; return actionBinding;
} }
@@ -84,13 +87,11 @@ namespace BlackGui
void CGuiActionBindHandler::unbind() void CGuiActionBindHandler::unbind()
{ {
Q_ASSERT_X(CInputManager::instance(), Q_FUNC_INFO, "Missing input manager");
if (this->hasTarget()) if (this->hasTarget())
{
if (CInputManager::instance())
{ {
CInputManager::instance()->unbind(this->m_index); CInputManager::instance()->unbind(this->m_index);
} }
}
this->reset(); this->reset();
} }
@@ -123,4 +124,16 @@ namespace BlackGui
{ {
return CFileUtils::appendFilePaths(path, name); return CFileUtils::appendFilePaths(path, name);
} }
const QString &CGuiActionBindHandler::pathSwiftPilotClient()
{
static const QString s("Pilot client UI/");
return s;
}
const QString &CGuiActionBindHandler::pathSwiftCore()
{
static const QString s("Core UI/");
return s;
}
} // namespace } // namespace

View File

@@ -46,6 +46,12 @@ namespace BlackGui
//! Corresponding BlackCore::CActionBind died, so delete CGuiActionBindHandler //! Corresponding BlackCore::CActionBind died, so delete CGuiActionBindHandler
static void actionBindWasDestroyed(CGuiActionBindHandler *bindHandler); static void actionBindWasDestroyed(CGuiActionBindHandler *bindHandler);
//! Path
static const QString &pathSwiftPilotClient();
//! Path
static const QString &pathSwiftCore();
private: private:
//! Constructor for QAction //! Constructor for QAction
CGuiActionBindHandler(QAction *action); CGuiActionBindHandler(QAction *action);

View File

@@ -14,8 +14,12 @@ namespace BlackGui
{ {
namespace Models namespace Models
{ {
CActionItem::CActionItem(const QString &action, const QString &name, CActionItem *parent) : CActionItem::CActionItem(const QString &action, const QString &name, CActionItem *parentItem) :
m_action(action), m_actionName(name), m_parentItem(parent) m_action(action), m_actionName(name), m_parentItem(parentItem)
{ }
CActionItem::CActionItem(const QString &action, const QString &name, const QPixmap &icon, CActionItem *parentItem) :
m_action(action), m_actionName(name), m_icon(icon), m_parentItem(parentItem)
{ } { }
CActionItem::~CActionItem() CActionItem::~CActionItem()

View File

@@ -14,6 +14,7 @@
#include <QList> #include <QList>
#include <QString> #include <QString>
#include <QPixmap>
namespace BlackGui namespace BlackGui
{ {
@@ -26,6 +27,9 @@ namespace BlackGui
//! Constructor //! Constructor
CActionItem(const QString &action, const QString &name, CActionItem *parentItem = nullptr); CActionItem(const QString &action, const QString &name, CActionItem *parentItem = nullptr);
//! Constructor
CActionItem(const QString &action, const QString &name, const QPixmap &icon, CActionItem *parentItem = nullptr);
//! Destructor //! Destructor
~CActionItem(); ~CActionItem();
@@ -41,6 +45,12 @@ namespace BlackGui
//! Number of children //! Number of children
int getChildCount() const; int getChildCount() const;
//! Icon
const QPixmap &getIcon() const { return m_icon; }
//! Set icon
void setIcon(const QPixmap &icon) { m_icon = icon; }
//! Has children? //! Has children?
bool hasChildren() const; bool hasChildren() const;
@@ -60,9 +70,10 @@ namespace BlackGui
CActionItem *getParentItem() const; CActionItem *getParentItem() const;
private: private:
QList<CActionItem *> m_childItems;
QString m_action; QString m_action;
QString m_actionName; QString m_actionName;
QPixmap m_icon;
QList<CActionItem *> m_childItems;
CActionItem *m_parentItem = nullptr; CActionItem *m_parentItem = nullptr;
}; };
} }

View File

@@ -10,11 +10,16 @@
#include "blackcore/inputmanager.h" #include "blackcore/inputmanager.h"
#include "blackgui/models/actionitem.h" #include "blackgui/models/actionitem.h"
#include "blackgui/models/actionmodel.h" #include "blackgui/models/actionmodel.h"
#include "blackmisc/icons.h"
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QStringBuilder>
#include <QtGlobal> #include <QtGlobal>
using namespace BlackMisc;
using namespace BlackCore;
namespace BlackGui namespace BlackGui
{ {
namespace Models namespace Models
@@ -41,9 +46,11 @@ namespace BlackGui
if (!index.isValid()) { return QVariant(); } if (!index.isValid()) { return QVariant(); }
const CActionItem *item = static_cast<CActionItem *>(index.internalPointer()); const CActionItem *item = static_cast<CActionItem *>(index.internalPointer());
Q_ASSERT_X(item, Q_FUNC_INFO, "Missing item");
if (role == Qt::DisplayRole) { return item->getActionName(); }
if (role == ActionRole) { return item->getAction(); } if (role == ActionRole) { return item->getAction(); }
if (role == Qt::DisplayRole) { return item->getActionName(); }
if (role == Qt::DecorationRole) { return item->getIcon(); }
return {}; return {};
} }
@@ -85,12 +92,10 @@ namespace BlackGui
int CActionModel::rowCount(const QModelIndex &parent) const int CActionModel::rowCount(const QModelIndex &parent) const
{ {
CActionItem *parentItem;
if (parent.column() > 0) { return 0; } if (parent.column() > 0) { return 0; }
const CActionItem *parentItem = parent.isValid() ?
if (!parent.isValid()) { parentItem = m_rootItem.data(); } static_cast<CActionItem *>(parent.internalPointer()) :
else { parentItem = static_cast<CActionItem *>(parent.internalPointer()); } m_rootItem.data();
return parentItem->getChildCount(); return parentItem->getChildCount();
} }
@@ -98,16 +103,23 @@ namespace BlackGui
{ {
m_rootItem.reset(new CActionItem(QString(), QString())); m_rootItem.reset(new CActionItem(QString(), QString()));
for (const auto &actionPath : BlackCore::CInputManager::instance()->allAvailableActions()) const QMap<QString, QPixmap> availableActionsAndIcons = CInputManager::instance()->allAvailableActionsAndIcons();
QStringList keys = availableActionsAndIcons.keys();
keys.sort();
for (const QString &actionPath : as_const(keys))
{ {
const auto tokens = actionPath.split("/", QString::SkipEmptyParts); QString currentPath;
const QStringList tokens = actionPath.split("/", QString::SkipEmptyParts);
CActionItem *parentItem = m_rootItem.data(); CActionItem *parentItem = m_rootItem.data();
for (const auto &token : tokens) for (const auto &token : tokens)
{ {
currentPath += QLatin1Char('/') % token;
CActionItem *child = parentItem->findChildByName(token); CActionItem *child = parentItem->findChildByName(token);
if (child == nullptr) if (child == nullptr)
{ {
child = new CActionItem(actionPath, token, parentItem); const bool isAction = currentPath == actionPath; // action istelf, or just a node?
const QPixmap icon = isAction ? availableActionsAndIcons[actionPath] : CIcons::empty16();
child = new CActionItem(isAction ? actionPath : "", token, icon, parentItem);
parentItem->appendChild(child); parentItem->appendChild(child);
} }
Q_ASSERT(child); Q_ASSERT(child);

View File

@@ -77,7 +77,9 @@ void SwiftGuiStd::initMenus()
ui->menu_InfoAreas->addActions(ui->comp_MainInfoArea->getInfoAreaSelectActions(ui->menu_InfoAreas)); ui->menu_InfoAreas->addActions(ui->comp_MainInfoArea->getInfoAreaSelectActions(ui->menu_InfoAreas));
// for hotkeys // for hotkeys
m_menuHotkeyHandlers.append(CGuiActionBindHandler::bindMenu(ui->menu_InfoAreas, "Info areas")); const QString swift(CGuiActionBindHandler::pathSwiftPilotClient());
m_menuHotkeyHandlers.append(CGuiActionBindHandler::bindMenu(ui->menu_File, "File")); static const CActionBind swiftRoot(swift, CIcons::swift16());
m_menuHotkeyHandlers.append(CGuiActionBindHandler::bindMenu(ui->menu_Window, "Window")); m_menuHotkeyHandlers.append(CGuiActionBindHandler::bindMenu(ui->menu_InfoAreas, swift + "Info areas"));
m_menuHotkeyHandlers.append(CGuiActionBindHandler::bindMenu(ui->menu_File, swift + "File"));
m_menuHotkeyHandlers.append(CGuiActionBindHandler::bindMenu(ui->menu_Window, swift + "Window"));
} }