swift
guiactionbind.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2017 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "guiactionbind.h"
5 
6 #include "misc/fileutils.h"
7 #include "misc/imageutils.h"
8 
9 using namespace swift::misc;
10 using namespace swift::core;
11 
12 namespace swift::gui
13 {
14  CGuiActionBindHandler::CGuiActionBindHandler(QAction *action) : QObject(action), m_action(action)
15  {
16  this->connectDestroy(action);
17  connect(sApp, &CApplication::aboutToShutdown, this, &CGuiActionBindHandler::unbind);
18  }
19 
20  CGuiActionBindHandler::CGuiActionBindHandler(QAbstractButton *button) : QObject(button), m_button(button)
21  {
22  this->connectDestroy(button);
23  connect(sApp, &CApplication::aboutToShutdown, this, &CGuiActionBindHandler::unbind);
24  }
25 
26  CGuiActionBindHandler::~CGuiActionBindHandler() {}
27 
28  CActionBindings CGuiActionBindHandler::bindMenu(QMenu *menu, const QString &path)
29  {
30  Q_ASSERT(menu);
31  CActionBindings boundActions;
32  if (!menu || menu->isEmpty()) { return boundActions; }
33  for (QAction *action : menu->actions())
34  {
35  if (action->text().isEmpty()) { continue; }
36  if (action->isSeparator()) { continue; }
37 
38  const QString pathNew =
39  CGuiActionBindHandler::appendPath(path, action->text()).remove('&'); // remove E&xit key codes
40  if (action->menu()) { CGuiActionBindHandler::bindMenu(action->menu(), pathNew); }
41 
42  const bool hasIcon = !action->icon().isNull();
43  CGuiActionBindHandler *bindHandler = new CGuiActionBindHandler(action);
44  // MS 2019-10-08 [AFV integration] CActionBind constructor needs an icon index, not a QPixmap
45  // CActionBinding actionBinding(CActionBinding::create(pathNew, hasIcon ?
46  // action->icon().pixmap(CIcons::empty16().size()) : CIcons::empty16(), bindHandler,
47  // &CGuiActionBindHandler::boundFunction, [bindHandler]() {
48  // CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
49  CActionBinding actionBinding(CActionBinding::create(
50  pathNew, CIcons::StandardIconEmpty16, bindHandler, &CGuiActionBindHandler::boundFunction,
51  [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
52  Q_UNUSED(hasIcon)
53  bindHandler->m_index = actionBinding->getIndex();
54  boundActions.append(actionBinding); // takes ownership
55  }
56  return boundActions;
57  }
58 
59  CActionBinding CGuiActionBindHandler::bindButton(QAbstractButton *button, const QString &path, bool absoluteName)
60  {
61  Q_ASSERT(button);
62  const QString pathNew =
63  absoluteName ?
64  path :
65  CGuiActionBindHandler::appendPath(path, button->text()).remove('&'); // remove E&xit key codes
66  CGuiActionBindHandler *bindHandler = new CGuiActionBindHandler(button);
67  const bool hasIcon = !button->icon().isNull();
68  // MS 2019-10-08 [AFV integration] CActionBind constructor needs an icon index, not a QPixmap
69  // CActionBinding actionBinding(CActionBinding::create(pathNew, hasIcon ?
70  // button->icon().pixmap(CIcons::empty16().size()) : CIcons::empty16(), bindHandler,
71  // &CGuiActionBindHandler::boundFunction, [bindHandler]() {
72  // CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
73  CActionBinding actionBinding(CActionBinding::create(
74  pathNew, CIcons::StandardIconEmpty16, bindHandler, &CGuiActionBindHandler::boundFunction,
75  [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
76  Q_UNUSED(hasIcon)
77  bindHandler->m_index = actionBinding->getIndex();
78  return actionBinding;
79  }
80 
81  void CGuiActionBindHandler::actionBindWasDestroyed(CGuiActionBindHandler *bindHandler)
82  {
83  if (!bindHandler) { return; }
84  bindHandler->reset();
85  // do not delete, as it might be still referenced somewhere
86  }
87 
88  void CGuiActionBindHandler::connectDestroy(QObject *object)
89  {
90  // if the action is destroyed from somewhere else I unbind myself
91  QObject::connect(object, &QObject::destroyed, [=] { this->unbind(); });
92  }
93 
94  void CGuiActionBindHandler::unbind()
95  {
96  if (this->hasTarget())
97  {
98  Q_ASSERT_X(sApp && sApp->getInputManager(), Q_FUNC_INFO, "Missing input manager");
99  sApp->getInputManager()->unbind(m_index);
100  }
101  this->reset();
102  }
103 
104  void CGuiActionBindHandler::reset()
105  {
106  m_index = -1;
107  m_button = nullptr;
108  m_action = nullptr;
109  }
110 
111  bool CGuiActionBindHandler::hasTarget() const { return (m_button || m_action) && m_index >= 0; }
112 
113  void CGuiActionBindHandler::boundFunction(bool enabled)
114  {
115  if (!enabled || !this->hasTarget()) { return; }
116  if (m_action) { m_action->trigger(); }
117  else if (m_button) { m_button->click(); }
118  }
119 
120  QString CGuiActionBindHandler::appendPath(const QString &path, const QString &name)
121  {
122  return CFileUtils::appendFilePaths(path, name);
123  }
124 
125  const QString &CGuiActionBindHandler::pathSwiftPilotClient()
126  {
127  static const QString s("Pilot client UI/");
128  return s;
129  }
130 
131  const QString &CGuiActionBindHandler::pathSwiftCore()
132  {
133  static const QString s("Core UI/");
134  return s;
135  }
136 } // namespace swift::gui
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
CInputManager * getInputManager() const
The input manager, if available.
Definition: application.h:302
void unbind(int index)
Unbind a slot.
QObject derived handler to be registered with swift::core::CActionBind.
Definition: guiactionbind.h:21
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
QSharedPointer< CActionBind > CActionBinding
Single binding.
Definition: actionbind.h:78
QList< CActionBinding > CActionBindings
List of bindings.
Definition: actionbind.h:81
GUI related classes.
Free functions in swift::misc.