File indexing completed on 2024-09-01 13:31:37
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2002 Simon Hausmann <hausmann@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "ktoolbarhandler_p.h" 0009 0010 #include <QAction> 0011 #include <QDomDocument> 0012 #include <QMenu> 0013 #include <QPointer> 0014 0015 #include <KActionMenu> 0016 #include <KAuthorized> 0017 #include <KLocalizedString> 0018 0019 #include "kactioncollection.h" 0020 #include "ktoggletoolbaraction.h" 0021 #include "ktoolbar.h" 0022 #include "kxmlguifactory.h" 0023 #include "kxmlguiwindow.h" 0024 0025 namespace 0026 { 0027 const char actionListName[] = "show_menu_and_toolbar_actionlist"; 0028 0029 const char guiDescription[] = 0030 "" 0031 "<!DOCTYPE gui><gui name=\"StandardToolBarMenuHandler\">" 0032 "<MenuBar>" 0033 " <Menu name=\"settings\">" 0034 " <ActionList name=\"%1\" />" 0035 " </Menu>" 0036 "</MenuBar>" 0037 "</gui>"; 0038 0039 class BarActionBuilder 0040 { 0041 public: 0042 BarActionBuilder(KActionCollection *actionCollection, KXmlGuiWindow *mainWindow, QVector<KToolBar *> &oldToolBarList) 0043 : m_actionCollection(actionCollection) 0044 , m_mainWindow(mainWindow) 0045 , m_needsRebuild(false) 0046 { 0047 const QList<KToolBar *> toolBars = m_mainWindow->findChildren<KToolBar *>(); 0048 0049 for (KToolBar *toolBar : toolBars) { 0050 if (toolBar->mainWindow() != m_mainWindow) { 0051 continue; 0052 } 0053 0054 if (!oldToolBarList.contains(toolBar)) { 0055 m_needsRebuild = true; 0056 } 0057 0058 m_toolBars.append(toolBar); 0059 } 0060 0061 if (!m_needsRebuild) { 0062 m_needsRebuild = (oldToolBarList.count() != m_toolBars.count()); 0063 } 0064 } 0065 0066 bool needsRebuild() const 0067 { 0068 return m_needsRebuild; 0069 } 0070 0071 QList<QAction *> create() 0072 { 0073 QList<QAction *> actions; 0074 0075 if (!m_needsRebuild) { 0076 return actions; 0077 } 0078 0079 for (KToolBar *bar : std::as_const(m_toolBars)) { 0080 handleToolBar(bar); 0081 } 0082 0083 if (m_toolBarActions.count() == 0) { 0084 return actions; 0085 } 0086 0087 if (m_toolBarActions.count() == 1) { 0088 KToggleToolBarAction *action = static_cast<KToggleToolBarAction *>(m_toolBarActions.first()); 0089 action->setText(KStandardShortcut::label(KStandardShortcut::ShowToolbar)); 0090 return m_toolBarActions; 0091 } 0092 0093 KActionMenu *menuAction = new KActionMenu(i18n("Toolbars Shown"), m_actionCollection); 0094 m_actionCollection->addAction(QStringLiteral("toolbars_submenu_action"), menuAction); 0095 0096 for (QAction *action : std::as_const(m_toolBarActions)) { 0097 menuAction->menu()->addAction(action); 0098 } 0099 0100 actions.append(menuAction); 0101 0102 return actions; 0103 } 0104 0105 const QVector<KToolBar *> &toolBars() const 0106 { 0107 return m_toolBars; 0108 } 0109 0110 private: 0111 void handleToolBar(KToolBar *toolBar) 0112 { 0113 KToggleToolBarAction *action = new KToggleToolBarAction(toolBar, toolBar->windowTitle(), m_actionCollection); 0114 m_actionCollection->addAction(toolBar->objectName(), action); 0115 0116 // ## tooltips, whatsthis? 0117 m_toolBarActions.append(action); 0118 } 0119 0120 KActionCollection *m_actionCollection; 0121 KXmlGuiWindow *m_mainWindow; 0122 0123 QVector<KToolBar *> m_toolBars; 0124 QList<QAction *> m_toolBarActions; 0125 0126 bool m_needsRebuild : 1; 0127 }; 0128 } 0129 0130 using namespace KDEPrivate; 0131 0132 class Q_DECL_HIDDEN ToolBarHandler::Private 0133 { 0134 public: 0135 Private(ToolBarHandler *_parent) 0136 : parent(_parent) 0137 { 0138 } 0139 0140 void clientAdded(KXMLGUIClient *client) 0141 { 0142 Q_UNUSED(client) 0143 parent->setupActions(); 0144 } 0145 0146 void init(KXmlGuiWindow *mainWindow); 0147 void connectToActionContainers(); 0148 void connectToActionContainer(QAction *action); 0149 void connectToActionContainer(QWidget *container); 0150 0151 ToolBarHandler *parent; 0152 QPointer<KXmlGuiWindow> mainWindow; 0153 QList<QAction *> actions; 0154 QVector<KToolBar *> toolBars; 0155 }; 0156 0157 void ToolBarHandler::Private::init(KXmlGuiWindow *mw) 0158 { 0159 mainWindow = mw; 0160 0161 QObject::connect(mainWindow->guiFactory(), &KXMLGUIFactory::clientAdded, parent, &ToolBarHandler::clientAdded); 0162 0163 if (parent->domDocument().documentElement().isNull()) { 0164 QString completeDescription = QString::fromLatin1(guiDescription).arg(QLatin1String(actionListName)); 0165 0166 parent->setXML(completeDescription, false /*merge*/); 0167 } 0168 } 0169 0170 void ToolBarHandler::Private::connectToActionContainers() 0171 { 0172 for (QAction *action : std::as_const(actions)) { 0173 connectToActionContainer(action); 0174 } 0175 } 0176 0177 void ToolBarHandler::Private::connectToActionContainer(QAction *action) 0178 { 0179 const auto associatedWidgets = action->associatedWidgets(); 0180 0181 for (auto *widget : associatedWidgets) { 0182 connectToActionContainer(widget); 0183 } 0184 } 0185 0186 void ToolBarHandler::Private::connectToActionContainer(QWidget *container) 0187 { 0188 QMenu *popupMenu = qobject_cast<QMenu *>(container); 0189 if (!popupMenu) { 0190 return; 0191 } 0192 0193 connect(popupMenu, &QMenu::aboutToShow, parent, &ToolBarHandler::setupActions); 0194 } 0195 0196 ToolBarHandler::ToolBarHandler(KXmlGuiWindow *mainWindow) 0197 : QObject(mainWindow) 0198 , KXMLGUIClient(mainWindow) 0199 , d(new Private(this)) 0200 { 0201 d->init(mainWindow); 0202 } 0203 0204 ToolBarHandler::ToolBarHandler(KXmlGuiWindow *mainWindow, QObject *parent) 0205 : QObject(parent) 0206 , KXMLGUIClient(mainWindow) 0207 , d(new Private(this)) 0208 { 0209 d->init(mainWindow); 0210 } 0211 0212 ToolBarHandler::~ToolBarHandler() 0213 { 0214 qDeleteAll(d->actions); 0215 d->actions.clear(); 0216 0217 delete d; 0218 } 0219 0220 QAction *ToolBarHandler::toolBarMenuAction() 0221 { 0222 Q_ASSERT(d->actions.count() == 1); 0223 return d->actions.first(); 0224 } 0225 0226 void ToolBarHandler::setupActions() 0227 { 0228 if (!factory() || !d->mainWindow) { 0229 return; 0230 } 0231 0232 BarActionBuilder builder(actionCollection(), d->mainWindow, d->toolBars); 0233 0234 if (!builder.needsRebuild()) { 0235 return; 0236 } 0237 0238 unplugActionList(QLatin1String(actionListName)); 0239 0240 qDeleteAll(d->actions); 0241 d->actions.clear(); 0242 0243 d->actions = builder.create(); 0244 0245 d->toolBars = builder.toolBars(); 0246 0247 // We have no XML file associated with our action collection, so load settings from KConfig 0248 actionCollection()->readSettings(); // #233712 0249 0250 if (KAuthorized::authorizeAction(QStringLiteral("options_show_toolbar"))) { 0251 plugActionList(QLatin1String(actionListName), d->actions); 0252 } 0253 0254 d->connectToActionContainers(); 0255 } 0256 0257 void ToolBarHandler::clientAdded(KXMLGUIClient *client) 0258 { 0259 d->clientAdded(client); 0260 } 0261 0262 #include "moc_ktoolbarhandler_p.cpp"