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  CActionBindings CGuiActionBindHandler::bindMenu(QMenu *menu, const QString &path)
27  {
28  Q_ASSERT(menu);
29  CActionBindings boundActions;
30  if (!menu || menu->isEmpty()) { return boundActions; }
31  for (QAction *action : menu->actions())
32  {
33  if (action->text().isEmpty()) { continue; }
34  if (action->isSeparator()) { continue; }
35 
36  const QString pathNew =
37  CGuiActionBindHandler::appendPath(path, action->text()).remove('&'); // remove E&xit key codes
38  if (action->menu()) { CGuiActionBindHandler::bindMenu(action->menu(), pathNew); }
39 
40  const bool hasIcon = !action->icon().isNull();
41  auto *bindHandler = new CGuiActionBindHandler(action);
42  // MS 2019-10-08 [AFV integration] CActionBind constructor needs an icon index, not a QPixmap
43  // CActionBinding actionBinding(CActionBinding::create(pathNew, hasIcon ?
44  // action->icon().pixmap(CIcons::empty16().size()) : CIcons::empty16(), bindHandler,
45  // &CGuiActionBindHandler::boundFunction, [bindHandler]() {
46  // CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
47  CActionBinding actionBinding(CActionBinding::create(
48  pathNew, CIcons::StandardIconEmpty16, bindHandler, &CGuiActionBindHandler::boundFunction,
49  [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
50  Q_UNUSED(hasIcon)
51  bindHandler->m_index = actionBinding->getIndex();
52  boundActions.append(actionBinding); // takes ownership
53  }
54  return boundActions;
55  }
56 
57  CActionBinding CGuiActionBindHandler::bindButton(QAbstractButton *button, const QString &path, bool absoluteName)
58  {
59  Q_ASSERT(button);
60  const QString pathNew =
61  absoluteName ?
62  path :
63  CGuiActionBindHandler::appendPath(path, button->text()).remove('&'); // remove E&xit key codes
64  auto *bindHandler = new CGuiActionBindHandler(button);
65  const bool hasIcon = !button->icon().isNull();
66  // MS 2019-10-08 [AFV integration] CActionBind constructor needs an icon index, not a QPixmap
67  // CActionBinding actionBinding(CActionBinding::create(pathNew, hasIcon ?
68  // button->icon().pixmap(CIcons::empty16().size()) : CIcons::empty16(), bindHandler,
69  // &CGuiActionBindHandler::boundFunction, [bindHandler]() {
70  // CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
71  CActionBinding actionBinding(CActionBinding::create(
72  pathNew, CIcons::StandardIconEmpty16, bindHandler, &CGuiActionBindHandler::boundFunction,
73  [bindHandler]() { CGuiActionBindHandler::actionBindWasDestroyed(bindHandler); }));
74  Q_UNUSED(hasIcon)
75  bindHandler->m_index = actionBinding->getIndex();
76  return actionBinding;
77  }
78 
79  void CGuiActionBindHandler::actionBindWasDestroyed(CGuiActionBindHandler *bindHandler)
80  {
81  if (!bindHandler) { return; }
82  bindHandler->reset();
83  // do not delete, as it might be still referenced somewhere
84  }
85 
86  void CGuiActionBindHandler::connectDestroy(QObject *object)
87  {
88  // if the action is destroyed from somewhere else I unbind myself
89  QObject::connect(object, &QObject::destroyed, [=] { this->unbind(); });
90  }
91 
92  void CGuiActionBindHandler::unbind()
93  {
94  if (this->hasTarget())
95  {
96  Q_ASSERT_X(sApp && sApp->getInputManager(), Q_FUNC_INFO, "Missing input manager");
97  sApp->getInputManager()->unbind(m_index);
98  }
99  this->reset();
100  }
101 
102  void CGuiActionBindHandler::reset()
103  {
104  m_index = -1;
105  m_button = nullptr;
106  m_action = nullptr;
107  }
108 
109  bool CGuiActionBindHandler::hasTarget() const { return (m_button || m_action) && m_index >= 0; }
110 
111  void CGuiActionBindHandler::boundFunction(bool enabled)
112  {
113  if (!enabled || !this->hasTarget()) { return; }
114  if (m_action) { m_action->trigger(); }
115  else if (m_button) { m_button->click(); }
116  }
117 
118  QString CGuiActionBindHandler::appendPath(const QString &path, const QString &name)
119  {
120  return CFileUtils::appendFilePaths(path, name);
121  }
122 
123  const QString &CGuiActionBindHandler::pathSwiftPilotClient()
124  {
125  static const QString s("Pilot client UI/");
126  return s;
127  }
128 
129  const QString &CGuiActionBindHandler::pathSwiftCore()
130  {
131  static const QString s("Core UI/");
132  return s;
133  }
134 } // 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
GUI related classes.
Free functions in swift::misc.
void append(QList< T > &&value)
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QTextStream & reset(QTextStream &stream)
QFuture< QtFuture::ArgsType< Signal >> connect(Sender *sender, Signal signal)
QList< QAction * > actions() const const