KXmlGui

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

KDE's Doxygen guidelines are available online.