KXmlGui

ktoolbarhandler.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2002 Simon Hausmann <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-only
6 */
7 
8 #include "ktoolbarhandler_p.h"
9 
10 #include <QDomDocument>
11 #include <QAction>
12 #include <QMenu>
13 #include <QLinkedList>
14 #include <QPointer>
15 
16 #include <kactionmenu.h>
17 #include <kauthorized.h>
18 #include <klocalizedstring.h>
19 
20 #include "kxmlguiwindow.h"
21 #include "ktoggletoolbaraction.h"
22 #include "ktoolbar.h"
23 #include "kxmlguifactory.h"
24 #include "kactioncollection.h"
25 
26 namespace
27 {
28 const char actionListName[] = "show_menu_and_toolbar_actionlist";
29 
30 const char guiDescription[] = ""
31  "<!DOCTYPE gui><gui name=\"StandardToolBarMenuHandler\">"
32  "<MenuBar>"
33  " <Menu name=\"settings\">"
34  " <ActionList name=\"%1\" />"
35  " </Menu>"
36  "</MenuBar>"
37  "</gui>";
38 
39 class BarActionBuilder
40 {
41 public:
42  BarActionBuilder(KActionCollection *actionCollection, KXmlGuiWindow *mainWindow,
43  QVector<KToolBar *> &oldToolBarList)
44  : m_actionCollection(actionCollection), m_mainWindow(mainWindow), m_needsRebuild(false)
45  {
46  const QList<KToolBar *> toolBars = m_mainWindow->findChildren<KToolBar *>();
47 
48  for (KToolBar *toolBar : toolBars) {
49  if (toolBar->mainWindow() != m_mainWindow) {
50  continue;
51  }
52 
53  if (!oldToolBarList.contains(toolBar)) {
54  m_needsRebuild = true;
55  }
56 
57  m_toolBars.append(toolBar);
58  }
59 
60  if (!m_needsRebuild) {
61  m_needsRebuild = (oldToolBarList.count() != m_toolBars.count());
62  }
63  }
64 
65  bool needsRebuild() const
66  {
67  return m_needsRebuild;
68  }
69 
71  {
72  QList<QAction *> actions;
73 
74  if (!m_needsRebuild) {
75  return actions;
76  }
77 
78  for (KToolBar *bar : qAsConst(m_toolBars)) {
79  handleToolBar(bar);
80  }
81 
82  if (m_toolBarActions.count() == 0) {
83  return actions;
84  }
85 
86  if (m_toolBarActions.count() == 1) {
87  KToggleToolBarAction *action = static_cast<KToggleToolBarAction *>(m_toolBarActions.first());
89  return m_toolBarActions;
90  }
91 
92  KActionMenu *menuAction = new KActionMenu(i18n("Toolbars Shown"), m_actionCollection);
93  m_actionCollection->addAction(QStringLiteral("toolbars_submenu_action"), menuAction);
94 
95  for (QAction *action : qAsConst(m_toolBarActions)) {
96  menuAction->menu()->addAction(action);
97  }
98 
99  actions.append(menuAction);
100 
101  return actions;
102  }
103 
104  const QVector<KToolBar *> &toolBars() const
105  {
106  return m_toolBars;
107  }
108 
109 private:
110  void handleToolBar(KToolBar *toolBar)
111  {
113  toolBar,
114  toolBar->windowTitle(),
115  m_actionCollection);
116  m_actionCollection->addAction(toolBar->objectName(), action);
117 
118  // ## tooltips, whatsthis?
119  m_toolBarActions.append(action);
120  }
121 
122  KActionCollection *m_actionCollection;
123  KXmlGuiWindow *m_mainWindow;
124 
125  QVector<KToolBar *> m_toolBars;
126  QList<QAction *> m_toolBarActions;
127 
128  bool m_needsRebuild : 1;
129 };
130 }
131 
132 using namespace KDEPrivate;
133 
134 class Q_DECL_HIDDEN ToolBarHandler::Private
135 {
136 public:
137  Private(ToolBarHandler *_parent)
138  : parent(_parent)
139  {
140  }
141 
142  void clientAdded(KXMLGUIClient *client)
143  {
144  Q_UNUSED(client)
145  parent->setupActions();
146  }
147 
148  void init(KXmlGuiWindow *mainWindow);
149  void connectToActionContainers();
150  void connectToActionContainer(QAction *action);
151  void connectToActionContainer(QWidget *container);
152 
153  ToolBarHandler *parent;
154  QPointer<KXmlGuiWindow> mainWindow;
155  QList<QAction *> actions;
156  QVector<KToolBar *> toolBars;
157 };
158 
159 void ToolBarHandler::Private::init(KXmlGuiWindow *mw)
160 {
161  mainWindow = mw;
162 
163  QObject::connect(mainWindow->guiFactory(), &KXMLGUIFactory::clientAdded,
164  parent, &ToolBarHandler::clientAdded);
165 
166  if (parent->domDocument().documentElement().isNull()) {
167 
168  QString completeDescription = QString::fromLatin1(guiDescription)
169  .arg(QLatin1String(actionListName));
170 
171  parent->setXML(completeDescription, false /*merge*/);
172  }
173 }
174 
175 void ToolBarHandler::Private::connectToActionContainers()
176 {
177  for (QAction *action : qAsConst(actions)) {
178  connectToActionContainer(action);
179  }
180 }
181 
182 void ToolBarHandler::Private::connectToActionContainer(QAction *action)
183 {
184  const auto associatedWidgets = action->associatedWidgets();
185 
186  for (auto *widget : associatedWidgets) {
187  connectToActionContainer(widget);
188  }
189 }
190 
191 void ToolBarHandler::Private::connectToActionContainer(QWidget *container)
192 {
193  QMenu *popupMenu = qobject_cast<QMenu *>(container);
194  if (!popupMenu) {
195  return;
196  }
197 
198  connect(popupMenu, &QMenu::aboutToShow,
199  parent, &ToolBarHandler::setupActions);
200 }
201 
202 ToolBarHandler::ToolBarHandler(KXmlGuiWindow *mainWindow)
203  : QObject(mainWindow), KXMLGUIClient(mainWindow),
204  d(new Private(this))
205 {
206  d->init(mainWindow);
207 }
208 
209 ToolBarHandler::ToolBarHandler(KXmlGuiWindow *mainWindow, QObject *parent)
210  : QObject(parent), KXMLGUIClient(mainWindow),
211  d(new Private(this))
212 {
213  d->init(mainWindow);
214 }
215 
216 ToolBarHandler::~ToolBarHandler()
217 {
218  qDeleteAll(d->actions);
219  d->actions.clear();
220 
221  delete d;
222 }
223 
224 QAction *ToolBarHandler::toolBarMenuAction()
225 {
226  Q_ASSERT(d->actions.count() == 1);
227  return d->actions.first();
228 }
229 
230 void ToolBarHandler::setupActions()
231 {
232  if (!factory() || !d->mainWindow) {
233  return;
234  }
235 
236  BarActionBuilder builder(actionCollection(), d->mainWindow, d->toolBars);
237 
238  if (!builder.needsRebuild()) {
239  return;
240  }
241 
242  unplugActionList(QLatin1String(actionListName));
243 
244  qDeleteAll(d->actions);
245  d->actions.clear();
246 
247  d->actions = builder.create();
248 
249  d->toolBars = builder.toolBars();
250 
251  // We have no XML file associated with our action collection, so load settings from KConfig
252  actionCollection()->readSettings(); // #233712
253 
254  if (KAuthorized::authorizeAction(QStringLiteral("options_show_toolbar"))) {
255  plugActionList(QLatin1String(actionListName), d->actions);
256  }
257 
258  d->connectToActionContainers();
259 }
260 
261 void ToolBarHandler::clientAdded(KXMLGUIClient* client)
262 {
263  d->clientAdded(client);
264 }
void setText(const QString &text)
A container for a set of QAction objects.
A KXMLGUIClient can be used with KXMLGUIFactory to create a GUI from actions and an XML document...
Definition: kxmlguiclient.h:38
QAction * create(StandardAction id, const QObject *recvr, Func slot, QObject *parent)
QAction * addAction(const QString &text)
An action that takes care of everything associated with showing or hiding a toolbar by a menu action...
bool contains(const T &value) const const
void append(const T &value)
void aboutToShow()
Top level main window with predefined action layout.
Definition: kxmlguiwindow.h:45
QString label(StandardShortcut id)
QString i18n(const char *text, const TYPE &arg...)
Floatable toolbar with auto resize.
Definition: ktoolbar.h:59
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
int count(const T &value) const const
QList< QWidget * > associatedWidgets() const const
QString fromLatin1(const char *str, int size)
KCONFIGCORE_EXPORT bool authorizeAction(const QString &action)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QMenu * menu() const const
void readSettings(KConfigGroup *config=nullptr)
Read all key associations from config.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Aug 12 2020 22:50:46 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.