Krita Source Code Documentation
Loading...
Searching...
No Matches
kxmlguibuilder.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 SPDX-FileCopyrightText: 2000 Simon Hausmann <hausmann@kde.org>
3 SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "kxmlguibuilder.h"
9
10#include "kxmlguiclient.h"
11#include "ktoolbar.h"
12#include "kmainwindow.h"
13#include "kxmlguiwindow.h"
14
15#include <klocalizedstring.h>
16
17#include <QDomElement>
18#include <QObject>
19#include <QStringList>
20#include <QAction>
21#include <QMenu>
22#include <QMenuBar>
23#include <QStatusBar>
24#include <QDebug>
25
26#include <kis_icon_utils.h>
27
28#if defined(KCONFIG_BEFORE_5_24)
29# define authorizeAction authorizeKAction
30#endif
31
32using namespace KDEPrivate;
33
35{
36public:
39
40 QWidget *m_widget {0};
41
43 QString tagMenuBar;
44 QString tagMenu;
45 QString tagToolBar;
46 QString tagStatusBar;
47
48 QString tagSeparator;
50 QString tagMenuTitle;
51
52 QString attrName;
54
55 QString attrDomain;
56 QString attrText1;
57 QString attrText2;
58 QString attrContext;
59
60 QString attrIcon;
61
63};
64
67{
68 d->m_widget = widget;
69
70 d->tagMainWindow = QStringLiteral("mainwindow");
71 d->tagMenuBar = QStringLiteral("menubar");
72 d->tagMenu = QStringLiteral("menu");
73 d->tagToolBar = QStringLiteral("toolbar");
74 d->tagStatusBar = QStringLiteral("statusbar");
75
76 d->tagSeparator = QStringLiteral("separator");
77 d->tagTearOffHandle = QStringLiteral("tearoffhandle");
78 d->tagMenuTitle = QStringLiteral("title");
79
80 d->attrName = QStringLiteral("name");
81 d->attrLineSeparator = QStringLiteral("lineseparator");
82
83 d->attrDomain = QStringLiteral("translationDomain");
84 d->attrText1 = QStringLiteral("text");
85 d->attrText2 = QStringLiteral("Text");
86 d->attrContext = QStringLiteral("context");
87
88 d->attrIcon = QStringLiteral("icon");
89}
90
95
97{
98 return d->m_widget;
99}
100
102{
103 QStringList res;
104 res << d->tagMenu << d->tagToolBar << d->tagMainWindow << d->tagMenuBar << d->tagStatusBar;
105
106 return res;
107}
108
109QWidget *KisKXMLGUIBuilder::createContainer(QWidget *parent, int index, const QDomElement &element, QAction *&containerAction)
110{
111 containerAction = 0;
112
113 if (element.attribute(QStringLiteral("deleted")).toLower() == QLatin1String("true")) {
114 return 0;
115 }
116
117 const QString tagName = element.tagName().toLower();
118 if (tagName == d->tagMainWindow) {
119 KisKMainWindow *mainwindow = qobject_cast<KisKMainWindow *>(d->m_widget); // could be 0
120 return mainwindow;
121 }
122
123 if (tagName == d->tagMenuBar) {
124 KisKMainWindow *mainWin = qobject_cast<KisKMainWindow *>(d->m_widget);
125 QMenuBar *bar = 0;
126 if (mainWin) {
127 bar = mainWin->menuBar();
128 }
129 if (!bar) {
130 bar = new QMenuBar(d->m_widget);
131 }
132 bar->show();
133 return bar;
134 }
135
136 if (tagName == d->tagMenu) {
137 // Look up to see if we are inside a mainwindow. If yes, then
138 // use it as parent widget (to get kaction to plug itself into the
139 // mainwindow). Don't use a popupmenu as parent widget, otherwise
140 // the popup won't be hidden if it is used as a standalone menu as well.
141 //
142 // Note: menus with a parent of 0, coming from child clients, can be
143 // leaked if the child client is deleted without a proper removeClient call, though.
144
145 QWidget *p = parent;
146
147 if (!p && qobject_cast<QMainWindow *>(d->m_widget)) {
148 p = d->m_widget;
149 }
150
151 while (p && !qobject_cast<QMainWindow *>(p)) {
152 p = p->parentWidget();
153 }
154
155 QString name = element.attribute(d->attrName);
156
157 QMenu *popup = new QMenu(p);
158 popup->setObjectName(name);
159
160 QString i18nText;
161 QDomElement textElem = element.namedItem(d->attrText1).toElement();
162 if (textElem.isNull()) { // try with capital T
163 textElem = element.namedItem(d->attrText2).toElement();
164 }
165 const QString text = textElem.text();
166 const QString context = textElem.attribute(d->attrContext);
167
168 //qDebug(260) << "DOMAIN" << KLocalizedString::applicationDomain();
169 //qDebug(260) << "ELEMENT TEXT:" << text;
170
171 if (text.isEmpty()) { // still no luck
172 i18nText = i18n("No text");
173 } else {
174 QByteArray domain = textElem.attribute(d->attrDomain).toUtf8();
175 if (domain.isEmpty()) {
176 domain = element.ownerDocument().documentElement().attribute(d->attrDomain).toUtf8();
177 if (domain.isEmpty()) {
178 domain = KLocalizedString::applicationDomain();
179 }
180 }
181 if (context.isEmpty()) {
182 i18nText = i18nd(domain.constData(), text.toUtf8().constData());
183 } else {
184 i18nText = i18ndc(domain.constData(), context.toUtf8().constData(), text.toUtf8().constData());
185 }
186 }
187
188 //qDebug(260) << "ELEMENT i18n TEXT:" << i18nText;
189
190 const QString icon = element.attribute(d->attrIcon);
191 QIcon pix;
192 if (!icon.isEmpty()) {
193 pix = KisIconUtils::loadIcon(icon);
194 }
195
196 if (parent) {
197 QAction *act = popup->menuAction();
198 if (!icon.isEmpty()) {
199 act->setIcon(pix);
200 }
201 act->setText(i18nText);
202 if (index == -1 || index >= parent->actions().count()) {
203 parent->addAction(act);
204 } else {
205 parent->insertAction(parent->actions().value(index), act);
206 }
207 containerAction = act;
208 containerAction->setObjectName(name);
209 }
210
211 return popup;
212 }
213
214 if (tagName == d->tagToolBar) {
215 QString name = element.attribute(d->attrName);
216
217 KisToolBar *bar = static_cast<KisToolBar *>(d->m_widget->findChild<KisToolBar *>(name));
218 if (!bar) {
219 bar = new KisToolBar(name, d->m_widget, false);
220 }
221
222 if (qobject_cast<KisKMainWindow *>(d->m_widget)) {
223 if (d->m_client && !d->m_client->xmlFile().isEmpty()) {
225 }
226 }
227
228 bar->loadState(element);
229
230 return bar;
231 }
232
233 if (tagName == d->tagStatusBar) {
234 KisKMainWindow *mainWin = qobject_cast<KisKMainWindow *>(d->m_widget);
235 if (mainWin) {
236 mainWin->statusBar()->show();
237 return mainWin->statusBar();
238 }
239 QStatusBar *bar = new QStatusBar(d->m_widget);
240 return bar;
241 }
242
243 return 0L;
244}
245
246void KisKXMLGUIBuilder::removeContainer(QWidget *container, QWidget *parent, QDomElement &element, QAction *containerAction)
247{
248 // Warning parent can be 0L
249
250 if (qobject_cast<QMenu *>(container)) {
251 if (parent) {
252 parent->removeAction(containerAction);
253 }
254
255 delete container;
256 } else if (qobject_cast<KisToolBar *>(container)) {
257 KisToolBar *tb = static_cast<KisToolBar *>(container);
258
259 tb->saveState(element);
260 delete tb;
261 } else if (qobject_cast<QMenuBar *>(container)) {
262 QMenuBar *mb = static_cast<QMenuBar *>(container);
263 mb->hide();
264 // Don't delete menubar - it can be reused by createContainer.
265 // If you decide that you do need to delete the menubar, make
266 // sure that QMainWindow::d->mb does not point to a deleted
267 // menubar object.
268 } else if (qobject_cast<QStatusBar *>(container)) {
269 if (qobject_cast<KisKMainWindow *>(d->m_widget)) {
270 container->hide();
271 } else {
272 delete static_cast<QStatusBar *>(container);
273 }
274 } else {
275 qWarning() << "Unhandled container to remove : " << container->metaObject()->className();
276 }
277}
278
280{
281 QStringList res;
283 return res;
284}
285
286QAction *KisKXMLGUIBuilder::createCustomElement(QWidget *parent, int index, const QDomElement &element)
287{
288 QAction *before = 0L;
289 if (index > 0 && index < parent->actions().count()) {
290 before = parent->actions().at(index);
291 }
292
293 const QString tagName = element.tagName().toLower();
294 if (tagName == d->tagSeparator) {
295 if (QMenu *menu = qobject_cast<QMenu *>(parent)) {
296 // QMenu already cares for leading/trailing/repeated separators
297 // no need to check anything
298 return menu->insertSeparator(before);
299 } else if (QMenuBar *bar = qobject_cast<QMenuBar *>(parent)) {
300 QAction *separatorAction = new QAction(bar);
301 separatorAction->setSeparator(true);
302 bar->insertAction(before, separatorAction);
303 return separatorAction;
304 } else if (KisToolBar *bar = qobject_cast<KisToolBar *>(parent)) {
305 /* FIXME KAction port - any need to provide a replacement for lineSeparator/normal separator?
306 bool isLineSep = true;
307
308 QDomNamedNodeMap attributes = element.attributes();
309 unsigned int i = 0;
310 for (; i < attributes.length(); i++ )
311 {
312 QDomAttr attr = attributes.item( i ).toAttr();
313
314 if ( attr.name().toLower() == d->attrLineSeparator &&
315 attr.value().toLower() == QStringLiteral("false") )
316 {
317 isLineSep = false;
318 break;
319 }
320 }
321
322 if ( isLineSep )
323 return bar->insertSeparator( index ? bar->actions()[index - 1] : 0L );
324 else*/
325
326 return bar->insertSeparator(before);
327 }
328 } else if (tagName == d->tagTearOffHandle) {
329 static_cast<QMenu *>(parent)->setTearOffEnabled(true);
330 } else if (tagName == d->tagMenuTitle) {
331 if (QMenu *m = qobject_cast<QMenu *>(parent)) {
332 QString i18nText;
333 const QString text = element.text();
334
335 if (text.isEmpty()) {
336 i18nText = i18n("No text");
337 } else {
338 QByteArray domain = element.attribute(d->attrDomain).toUtf8();
339 if (domain.isEmpty()) {
340 domain = element.ownerDocument().documentElement().attribute(d->attrDomain).toUtf8();
341 if (domain.isEmpty()) {
342 domain = KLocalizedString::applicationDomain();
343 }
344 }
345 i18nText = i18nd(domain.constData(), qPrintable(text));
346 }
347
348 QString icon = element.attribute(d->attrIcon);
349 QIcon pix;
350
351 if (!icon.isEmpty()) {
352 pix = KisIconUtils::loadIcon(icon);
353 }
354
355 if (!icon.isEmpty()) {
356 return m->insertSection(before, pix, i18nText);
357 } else {
358 return m->insertSection(before, i18nText);
359 }
360 }
361 }
362
363 QAction *blank = new QAction(parent);
364 blank->setVisible(false);
365 parent->insertAction(before, blank);
366 return blank;
367}
368
369void KisKXMLGUIBuilder::removeCustomElement(QWidget *parent, QAction *action)
370{
371 parent->removeAction(action);
372}
373
378
380{
381 d->m_client = client;
382}
383
385{
386 KXmlGuiWindow *window = qobject_cast<KXmlGuiWindow *>(d->m_widget);
387 if (!window) {
388 return;
389 }
390#if 0
391 KisToolBar *toolbar = 0;
392 QListIterator<KisToolBar> it(((KisKMainWindow *)d->m_widget)->toolBarIterator());
393 while ((toolbar = it.current())) {
394 //qDebug(260) << "KisKXMLGUIBuilder::finalizeGUI toolbar=" << (void*)toolbar;
395 ++it;
396 toolbar->positionYourself();
397 }
398#else
399 window->finalizeGUI(false);
400#endif
401}
402
404{
405 /*BASE::virtual_hook( id, data );*/
406}
407
const Params2D p
KDE top level main window with predefined action layout
void finalizeGUI(KisKXMLGUIClient *client) override
KDE top level main window
Definition kmainwindow.h:89
KisKXMLGUIClient * m_client
virtual QAction * createCustomElement(QWidget *parent, int index, const QDomElement &element)
KisKXMLGUIBuilder(QWidget *widget)
virtual QWidget * createContainer(QWidget *parent, int index, const QDomElement &element, QAction *&containerAction)
virtual void finalizeGUI(KisKXMLGUIClient *client)
virtual void removeCustomElement(QWidget *parent, QAction *action)
virtual QStringList customTags() const
virtual ~KisKXMLGUIBuilder()
virtual void removeContainer(QWidget *container, QWidget *parent, QDomElement &element, QAction *containerAction)
void setBuilderClient(KisKXMLGUIClient *client)
KisKXMLGUIBuilderPrivate *const d
virtual QStringList containerTags() const
virtual void virtual_hook(int id, void *data)
KisKXMLGUIClient * builderClient() const
virtual QString xmlFile() const
Floatable toolbar with auto resize.
Definition ktoolbar.h:47
void saveState(QDomElement &element) const
Definition ktoolbar.cpp:985
void loadState(const QDomElement &element)
Definition ktoolbar.cpp:860
void addXMLGUIClient(KisKXMLGUIClient *client)
Definition ktoolbar.cpp:845
QIcon loadIcon(const QString &name)