KXmlGui

ktoolbar.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2000 Reginald Stadlbauer <[email protected]>
4  SPDX-FileCopyrightText: 1997, 1998 Stephan Kulow <[email protected]>
5  SPDX-FileCopyrightText: 1997, 1998 Mark Donohoe <[email protected]>
6  SPDX-FileCopyrightText: 1997, 1998 Sven Radej <[email protected]>
7  SPDX-FileCopyrightText: 1997, 1998 Matthias Ettrich <[email protected]>
8  SPDX-FileCopyrightText: 1999 Chris Schlaeger <[email protected]>
9  SPDX-FileCopyrightText: 1999 Kurt Granroth <[email protected]>
10  SPDX-FileCopyrightText: 2005-2006 Hamish Rodda <[email protected]>
11 
12  SPDX-License-Identifier: LGPL-2.0-only
13 */
14 
15 #include "ktoolbar.h"
16 
17 #include <QAction>
18 #include <QActionGroup>
19 #include <QApplication>
20 #include <QDomElement>
21 #include <QDrag>
22 #include <QFrame>
23 #include <QLayout>
24 #include <QMenu>
25 #include <QMimeData>
26 #include <QMouseEvent>
27 #include <QPointer>
28 #ifdef QT_DBUS_LIB
29 #include <QDBusConnection>
30 #include <QDBusMessage>
31 #endif
32 
33 #include <KAuthorized>
34 #include <KConfig>
35 #include <KConfigGroup>
36 #include <KIconTheme>
37 #include <KLocalizedString>
38 #include <KSharedConfig>
39 #include <KStandardAction>
40 #include <KToggleAction>
41 
42 #include "kactioncollection.h"
43 #include "kedittoolbar.h"
44 #include "kxmlguifactory.h"
45 #include "kxmlguiwindow.h"
46 
47 #include "ktoolbarhelper_p.h"
48 
49 /*
50  Toolbar settings (e.g. icon size or toolButtonStyle)
51  =====================================================
52 
53  We have the following stack of settings (in order of priority) :
54  - user-specified settings (loaded/saved in KConfig)
55  - developer-specified settings in the XMLGUI file (if using xmlgui) (cannot change at runtime)
56  - KDE-global default (user-configurable; can change at runtime)
57  and when switching between kparts, they are saved as xml in memory,
58  which, in the unlikely case of no-kmainwindow-autosaving, could be
59  different from the user-specified settings saved in KConfig and would have
60  priority over it.
61 
62  So, in summary, without XML:
63  Global config / User settings (loaded/saved in kconfig)
64  and with XML:
65  Global config / App-XML attributes / User settings (loaded/saved in kconfig)
66 
67  And all those settings (except the KDE-global defaults) have to be stored in memory
68  since we cannot retrieve them at random points in time, not knowing the xml document
69  nor config file that holds these settings. Hence the iconSizeSettings and toolButtonStyleSettings arrays.
70 
71  For instance, if you change the KDE-global default, whether this makes a change
72  on a given toolbar depends on whether there are settings at Level_AppXML or Level_UserSettings.
73  Only if there are no settings at those levels, should the change of KDEDefault make a difference.
74 */
75 enum SettingLevel { Level_KDEDefault, Level_AppXML, Level_UserSettings, NSettingLevels };
76 enum { Unset = -1 };
77 
78 class KToolBarPrivate
79 {
80 public:
81  KToolBarPrivate(KToolBar *qq)
82  : q(qq)
83  , isMainToolBar(false)
84 #if KXMLGUI_BUILD_DEPRECATED_SINCE(5, 0)
85  , enableContext(true)
86 #endif
87  , unlockedMovable(true)
88  , contextOrient(nullptr)
89  , contextMode(nullptr)
90  , contextSize(nullptr)
91  , contextButtonTitle(nullptr)
92  , contextShowText(nullptr)
93  , contextButtonAction(nullptr)
94  , contextTop(nullptr)
95  , contextLeft(nullptr)
96  , contextRight(nullptr)
97  , contextBottom(nullptr)
98  , contextIcons(nullptr)
99  , contextTextRight(nullptr)
100  , contextText(nullptr)
101  , contextTextUnder(nullptr)
102  , contextLockAction(nullptr)
103  , dropIndicatorAction(nullptr)
104  , context(nullptr)
105  , dragAction(nullptr)
106  {
107  }
108 
109  void slotAppearanceChanged();
110  void slotContextAboutToShow();
111  void slotContextAboutToHide();
112  void slotContextLeft();
113  void slotContextRight();
114  void slotContextShowText();
115  void slotContextTop();
116  void slotContextBottom();
117  void slotContextIcons();
118  void slotContextText();
119  void slotContextTextRight();
120  void slotContextTextUnder();
121  void slotContextIconSize(QAction *action);
122  void slotLockToolBars(bool lock);
123 
124  void init(bool readConfig = true, bool isMainToolBar = false);
125  QString getPositionAsString() const;
126  QMenu *contextMenu(const QPoint &globalPos);
127  void setLocked(bool locked);
128  void adjustSeparatorVisibility();
129  void loadKDESettings();
130  void applyCurrentSettings();
131 
132  QAction *findAction(const QString &actionName, KXMLGUIClient **client = nullptr) const;
133 
134  static Qt::ToolButtonStyle toolButtonStyleFromString(const QString &style);
135  static QString toolButtonStyleToString(Qt::ToolButtonStyle);
136  static Qt::ToolBarArea positionFromString(const QString &position);
137  static Qt::ToolButtonStyle toolButtonStyleSetting();
138 
139  KToolBar *const q;
140  bool isMainToolBar : 1;
141 #if KXMLGUI_BUILD_DEPRECATED_SINCE(5, 0)
142  bool enableContext : 1;
143 #endif
144  bool unlockedMovable : 1;
145  static bool s_editable;
146  static bool s_locked;
147 
148  QSet<KXMLGUIClient *> xmlguiClients;
149 
150  QMenu *contextOrient;
151  QMenu *contextMode;
152  QMenu *contextSize;
153 
154  QAction *contextButtonTitle;
155  QAction *contextShowText;
156  QAction *contextButtonAction;
157  QAction *contextTop;
158  QAction *contextLeft;
159  QAction *contextRight;
160  QAction *contextBottom;
161  QAction *contextIcons;
162  QAction *contextTextRight;
163  QAction *contextText;
164  QAction *contextTextUnder;
165  KToggleAction *contextLockAction;
166 
167  struct ContextIconInfo {
168  QAction *iconAction = nullptr;
169  int iconSize = 0;
170  };
171 
172  std::vector<ContextIconInfo> m_contextIconSizes;
173 
174  class IntSetting
175  {
176  public:
177  IntSetting()
178  {
179  for (int &value : values) {
180  value = Unset;
181  }
182  }
183  int currentValue() const
184  {
185  int val = Unset;
186  for (int value : values) {
187  if (value != Unset) {
188  val = value;
189  }
190  }
191  return val;
192  }
193  // Default value as far as the user is concerned is kde-global + app-xml.
194  // If currentValue()==defaultValue() then nothing to write into kconfig.
195  int defaultValue() const
196  {
197  int val = Unset;
198  for (int level = 0; level < Level_UserSettings; ++level) {
199  if (values[level] != Unset) {
200  val = values[level];
201  }
202  }
203  return val;
204  }
205  QString toString() const
206  {
207  QString str;
208  for (int value : values) {
209  str += QString::number(value) + QLatin1Char(' ');
210  }
211  return str;
212  }
213  int &operator[](int index)
214  {
215  return values[index];
216  }
217 
218  private:
219  int values[NSettingLevels];
220  };
221  IntSetting iconSizeSettings;
222  IntSetting toolButtonStyleSettings; // either Qt::ToolButtonStyle or -1, hence "int".
223 
224  QList<QAction *> actionsBeingDragged;
225  QAction *dropIndicatorAction;
226 
227  QMenu *context;
228  QAction *dragAction;
229  QPoint dragStartPosition;
230 };
231 
232 bool KToolBarPrivate::s_editable = false;
233 bool KToolBarPrivate::s_locked = true;
234 
235 void KToolBarPrivate::init(bool readConfig, bool _isMainToolBar)
236 {
237  isMainToolBar = _isMainToolBar;
238  loadKDESettings();
239 
240  // also read in our configurable settings (for non-xmlgui toolbars)
241  if (readConfig) {
243  q->applySettings(cg);
244  }
245 
246  if (q->mainWindow()) {
247  // Get notified when settings change
253  }
254 
255  if (!KAuthorized::authorize(QStringLiteral("movable_toolbars"))) {
256  q->setMovable(false);
257  } else {
259  }
260 
261  q->toggleViewAction()->setEnabled(KAuthorized::authorizeAction(QStringLiteral("options_show_toolbar")));
262 
263  QObject::connect(q, &QToolBar::movableChanged, q, &KToolBar::slotMovableChanged);
264 
265  q->setAcceptDrops(true);
266 
267 #ifdef QT_DBUS_LIB
269  .connect(QString(), QStringLiteral("/KToolBar"), QStringLiteral("org.kde.KToolBar"), QStringLiteral("styleChanged"), q, SLOT(slotAppearanceChanged()));
270 #endif
272  slotAppearanceChanged();
273  });
274 }
275 
276 QString KToolBarPrivate::getPositionAsString() const
277 {
278  if (!q->mainWindow()) {
279  return QStringLiteral("None");
280  }
281  // get all of the stuff to save
282  switch (q->mainWindow()->toolBarArea(const_cast<KToolBar *>(q))) {
284  return QStringLiteral("Bottom");
285  case Qt::LeftToolBarArea:
286  return QStringLiteral("Left");
288  return QStringLiteral("Right");
289  case Qt::TopToolBarArea:
290  default:
291  return QStringLiteral("Top");
292  }
293 }
294 
295 QMenu *KToolBarPrivate::contextMenu(const QPoint &globalPos)
296 {
297  if (!context) {
298  context = new QMenu(q);
299  context->setIcon(QIcon::fromTheme(QStringLiteral("configure-toolbars")));
300  context->setTitle(i18nc("@title:menu", "Toolbar Settings"));
301 
302  contextButtonTitle = context->addSection(i18nc("@title:menu", "Show Text"));
303  contextShowText = context->addAction(QString(), q, [this]() {
304  slotContextShowText();
305  });
306 
307  context->addSection(i18nc("@title:menu", "Toolbar Settings"));
308 
309  contextOrient = new QMenu(i18nc("Toolbar orientation", "Orientation"), context);
310 
311  contextTop = contextOrient->addAction(i18nc("toolbar position string", "Top"), q, [this]() {
312  slotContextTop();
313  });
314  contextTop->setChecked(true);
315  contextLeft = contextOrient->addAction(i18nc("toolbar position string", "Left"), q, [this]() {
316  slotContextLeft();
317  });
318  contextRight = contextOrient->addAction(i18nc("toolbar position string", "Right"), q, [this]() {
319  slotContextRight();
320  });
321  contextBottom = contextOrient->addAction(i18nc("toolbar position string", "Bottom"), q, [this]() {
322  slotContextBottom();
323  });
324 
325  QActionGroup *positionGroup = new QActionGroup(contextOrient);
326  const auto orientActions = contextOrient->actions();
327  for (QAction *action : orientActions) {
328  action->setActionGroup(positionGroup);
329  action->setCheckable(true);
330  }
331 
332  contextMode = new QMenu(i18n("Text Position"), context);
333 
334  contextIcons = contextMode->addAction(i18nc("@item:inmenu", "Icons Only"), q, [this]() {
335  slotContextIcons();
336  });
337  contextText = contextMode->addAction(i18nc("@item:inmenu", "Text Only"), q, [this]() {
338  slotContextText();
339  });
340  contextTextRight = contextMode->addAction(i18nc("@item:inmenu", "Text Alongside Icons"), q, [this]() {
341  slotContextTextRight();
342  });
343  contextTextUnder = contextMode->addAction(i18nc("@item:inmenu", "Text Under Icons"), q, [this]() {
344  slotContextTextUnder();
345  });
346 
347  QActionGroup *textGroup = new QActionGroup(contextMode);
348  const auto modeActions = contextMode->actions();
349  for (QAction *action : modeActions) {
350  action->setActionGroup(textGroup);
351  action->setCheckable(true);
352  }
353 
354  contextSize = new QMenu(i18n("Icon Size"), context);
355 
356  auto *act = contextSize->addAction(i18nc("@item:inmenu Icon size", "Default"));
357  q->connect(act, &QAction::triggered, q, [this, act]() {
358  slotContextIconSize(act);
359  });
360  m_contextIconSizes.push_back({act, iconSizeSettings.defaultValue()});
361 
362  // Query the current theme for available sizes
363  KIconTheme *theme = KIconLoader::global()->theme();
364  QList<int> avSizes;
365  if (theme) {
366  avSizes = theme->querySizes(isMainToolBar ? KIconLoader::MainToolbar : KIconLoader::Toolbar);
367  }
368 
369  std::sort(avSizes.begin(), avSizes.end());
370 
371  if (avSizes.count() < 10) {
372  // Fixed or threshold type icons
373  for (int it : std::as_const(avSizes)) {
374  QString text;
375  if (it < 19) {
376  text = i18n("Small (%1x%2)", it, it);
377  } else if (it < 25) {
378  text = i18n("Medium (%1x%2)", it, it);
379  } else if (it < 35) {
380  text = i18n("Large (%1x%2)", it, it);
381  } else {
382  text = i18n("Huge (%1x%2)", it, it);
383  }
384 
385  auto *act = contextSize->addAction(text);
386  q->connect(act, &QAction::triggered, q, [this, act]() {
387  slotContextIconSize(act);
388  });
389  m_contextIconSizes.push_back({act, it});
390  }
391  } else {
392  // Scalable icons.
393  const int progression[] = {16, 22, 32, 48, 64, 96, 128, 192, 256};
394 
395  for (int p : progression) {
396  for (int it : std::as_const(avSizes)) {
397  if (it >= p) {
398  QString text;
399  if (it < 19) {
400  text = i18n("Small (%1x%2)", it, it);
401  } else if (it < 25) {
402  text = i18n("Medium (%1x%2)", it, it);
403  } else if (it < 35) {
404  text = i18n("Large (%1x%2)", it, it);
405  } else {
406  text = i18n("Huge (%1x%2)", it, it);
407  }
408 
409  auto *act = contextSize->addAction(text);
410  q->connect(act, &QAction::triggered, q, [this, act]() {
411  slotContextIconSize(act);
412  });
413  m_contextIconSizes.push_back({act, it});
414  break;
415  }
416  }
417  }
418  }
419 
420  QActionGroup *sizeGroup = new QActionGroup(contextSize);
421  const auto sizeActions = contextSize->actions();
422  for (QAction *action : sizeActions) {
423  action->setActionGroup(sizeGroup);
424  action->setCheckable(true);
425  }
426 
427  if (!q->toolBarsLocked() && !q->isMovable()) {
428  unlockedMovable = false;
429  }
430 
431  delete contextLockAction;
432  contextLockAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("system-lock-screen")), i18n("Lock Toolbar Positions"), q);
433  contextLockAction->setChecked(q->toolBarsLocked());
434  QObject::connect(contextLockAction, &KToggleAction::toggled, q, [this](bool checked) {
435  slotLockToolBars(checked);
436  });
437 
438  // Now add the actions to the menu
439  context->addMenu(contextMode);
440  context->addMenu(contextSize);
441  context->addMenu(contextOrient);
442  context->addSeparator();
443 
444  QObject::connect(context, &QMenu::aboutToShow, q, [this]() {
445  slotContextAboutToShow();
446  });
447  }
448 
449  contextButtonAction = q->actionAt(q->mapFromGlobal(globalPos));
450  if (contextButtonAction) {
451  contextShowText->setText(contextButtonAction->text());
452  contextShowText->setIcon(contextButtonAction->icon());
453  contextShowText->setCheckable(true);
454  }
455 
456  contextOrient->menuAction()->setVisible(!q->toolBarsLocked());
457  // Unplugging a submenu from abouttohide leads to the popupmenu floating around
458  // So better simply call that code from after exec() returns (DF)
459  // connect(context, SIGNAL(aboutToHide()), this, SLOT(slotContextAboutToHide()));
460 
461  // For tool buttons with delay popup or menu button popup (split button)
462  // show the actions of that button for ease of access.
463  // (no need to wait for the menu to open or aim at the arrow)
464  if (auto *contextToolButton = qobject_cast<QToolButton *>(q->widgetForAction(contextButtonAction))) {
465  if (contextToolButton->popupMode() == QToolButton::DelayedPopup || contextToolButton->popupMode() == QToolButton::MenuButtonPopup) {
466  if (auto *actionMenu = contextButtonAction->menu()) {
467  // In case it is populated on demand
468  Q_EMIT actionMenu->aboutToShow();
469 
470  auto *contextMenu = new QMenu(q);
471  contextMenu->setAttribute(Qt::WA_DeleteOnClose);
472 
473  const auto actions = actionMenu->actions();
474  if (!actions.isEmpty()) {
475  for (QAction *action : actions) {
476  contextMenu->addAction(action);
477  }
478 
479  // Now add the configure actions as submenu
480  contextMenu->addSeparator();
481  contextMenu->addMenu(context);
482  return contextMenu;
483  }
484  }
485  }
486  }
487 
488  return context;
489 }
490 
491 void KToolBarPrivate::setLocked(bool locked)
492 {
493  if (unlockedMovable) {
494  q->setMovable(!locked);
495  }
496 }
497 
498 void KToolBarPrivate::adjustSeparatorVisibility()
499 {
500  bool visibleNonSeparator = false;
501  int separatorToShow = -1;
502 
503  for (int index = 0; index < q->actions().count(); ++index) {
504  QAction *action = q->actions().at(index);
505  if (action->isSeparator()) {
506  if (visibleNonSeparator) {
507  separatorToShow = index;
508  visibleNonSeparator = false;
509  } else {
510  action->setVisible(false);
511  }
512  } else if (!visibleNonSeparator) {
513  if (action->isVisible()) {
514  visibleNonSeparator = true;
515  if (separatorToShow != -1) {
516  q->actions().at(separatorToShow)->setVisible(true);
517  separatorToShow = -1;
518  }
519  }
520  }
521  }
522 
523  if (separatorToShow != -1) {
524  q->actions().at(separatorToShow)->setVisible(false);
525  }
526 }
527 
528 Qt::ToolButtonStyle KToolBarPrivate::toolButtonStyleFromString(const QString &_style)
529 {
530  QString style = _style.toLower();
531  if (style == QLatin1String("textbesideicon") || style == QLatin1String("icontextright")) {
533  } else if (style == QLatin1String("textundericon") || style == QLatin1String("icontextbottom")) {
535  } else if (style == QLatin1String("textonly")) {
536  return Qt::ToolButtonTextOnly;
537  } else {
538  return Qt::ToolButtonIconOnly;
539  }
540 }
541 
542 QString KToolBarPrivate::toolButtonStyleToString(Qt::ToolButtonStyle style)
543 {
544  switch (style) {
546  default:
547  return QStringLiteral("IconOnly");
549  return QStringLiteral("TextBesideIcon");
551  return QStringLiteral("TextOnly");
553  return QStringLiteral("TextUnderIcon");
554  }
555 }
556 
557 Qt::ToolBarArea KToolBarPrivate::positionFromString(const QString &position)
558 {
559  Qt::ToolBarArea newposition = Qt::TopToolBarArea;
560  if (position == QLatin1String("left")) {
561  newposition = Qt::LeftToolBarArea;
562  } else if (position == QLatin1String("bottom")) {
563  newposition = Qt::BottomToolBarArea;
564  } else if (position == QLatin1String("right")) {
565  newposition = Qt::RightToolBarArea;
566  } else if (position == QLatin1String("none")) {
567  newposition = Qt::NoToolBarArea;
568  }
569  return newposition;
570 }
571 
572 // Global setting was changed
573 void KToolBarPrivate::slotAppearanceChanged()
574 {
575  loadKDESettings();
576  applyCurrentSettings();
577 }
578 
579 Qt::ToolButtonStyle KToolBarPrivate::toolButtonStyleSetting()
580 {
581  KConfigGroup group(KSharedConfig::openConfig(), "Toolbar style");
582  const QString fallback = KToolBarPrivate::toolButtonStyleToString(Qt::ToolButtonTextBesideIcon);
583  return KToolBarPrivate::toolButtonStyleFromString(group.readEntry("ToolButtonStyle", fallback));
584 }
585 
586 void KToolBarPrivate::loadKDESettings()
587 {
588  iconSizeSettings[Level_KDEDefault] = q->iconSizeDefault();
589 
590  if (isMainToolBar) {
591  toolButtonStyleSettings[Level_KDEDefault] = toolButtonStyleSetting();
592  } else {
593  const QString fallBack = toolButtonStyleToString(Qt::ToolButtonTextBesideIcon);
594  /**
595  TODO: if we get complaints about text beside icons on small screens,
596  try the following code out on such systems - aseigo.
597  // if we are on a small screen with a non-landscape ratio, then
598  // we revert to text under icons since width is probably not our
599  // friend in such cases
600  QDesktopWidget *desktop = QApplication::desktop();
601  QRect screenGeom = desktop->screenGeometry(desktop->primaryScreen());
602  qreal ratio = screenGeom.width() / qreal(screenGeom.height());
603 
604  if (screenGeom.width() < 1024 && ratio <= 1.4) {
605  fallBack = "TextUnderIcon";
606  }
607  **/
608 
609  KConfigGroup group(KSharedConfig::openConfig(), "Toolbar style");
610  const QString value = group.readEntry("ToolButtonStyleOtherToolbars", fallBack);
611  toolButtonStyleSettings[Level_KDEDefault] = KToolBarPrivate::toolButtonStyleFromString(value);
612  }
613 }
614 
615 // Call this after changing something in d->iconSizeSettings or d->toolButtonStyleSettings
616 void KToolBarPrivate::applyCurrentSettings()
617 {
618  // qCDebug(DEBUG_KXMLGUI) << q->objectName() << "iconSizeSettings:" << iconSizeSettings.toString() << "->" << iconSizeSettings.currentValue();
619  const int currentIconSize = iconSizeSettings.currentValue();
620  q->setIconSize(QSize(currentIconSize, currentIconSize));
621  // qCDebug(DEBUG_KXMLGUI) << q->objectName() << "toolButtonStyleSettings:" << toolButtonStyleSettings.toString() << "->" <<
622  // toolButtonStyleSettings.currentValue();
623  q->setToolButtonStyle(static_cast<Qt::ToolButtonStyle>(toolButtonStyleSettings.currentValue()));
624 
625  // And remember to save the new look later
626  KMainWindow *kmw = q->mainWindow();
627  if (kmw) {
628  kmw->setSettingsDirty();
629  }
630 }
631 
632 QAction *KToolBarPrivate::findAction(const QString &actionName, KXMLGUIClient **clientOut) const
633 {
634  for (KXMLGUIClient *client : xmlguiClients) {
635  QAction *action = client->actionCollection()->action(actionName);
636  if (action) {
637  if (clientOut) {
638  *clientOut = client;
639  }
640  return action;
641  }
642  }
643  return nullptr;
644 }
645 
646 void KToolBarPrivate::slotContextAboutToShow()
647 {
648  /**
649  * The idea here is to reuse the "static" part of the menu to save time.
650  * But the "Toolbars" action is dynamic (can be a single action or a submenu)
651  * and ToolBarHandler::setupActions() deletes it, so better not keep it around.
652  * So we currently plug/unplug the last two actions of the menu.
653  * Another way would be to keep around the actions and plug them all into a (new each time) popupmenu.
654  */
655 
656  KXmlGuiWindow *kmw = qobject_cast<KXmlGuiWindow *>(q->mainWindow());
657 
658  // try to find "configure toolbars" action
659  QAction *configureAction = nullptr;
661  configureAction = findAction(QLatin1String(actionName));
662 
663  if (!configureAction && kmw) {
664  configureAction = kmw->actionCollection()->action(QLatin1String(actionName));
665  }
666 
667  if (configureAction) {
668  context->addAction(configureAction);
669  }
670 
671  context->addAction(contextLockAction);
672 
673  if (kmw) {
675  // Only allow hiding a toolbar if the action is also plugged somewhere else (e.g. menubar)
676  QAction *tbAction = kmw->toolBarMenuAction();
677  if (!q->toolBarsLocked() && tbAction && !tbAction->associatedWidgets().isEmpty()) {
678  context->addAction(tbAction);
679  }
680  }
681 
682  KEditToolBar::setGlobalDefaultToolBar(q->QObject::objectName().toLatin1().constData());
683 
684  // Check the actions that should be checked
685  switch (q->toolButtonStyle()) {
687  default:
688  contextIcons->setChecked(true);
689  break;
691  contextTextRight->setChecked(true);
692  break;
694  contextText->setChecked(true);
695  break;
697  contextTextUnder->setChecked(true);
698  break;
699  }
700 
701  auto it = std::find_if(m_contextIconSizes.cbegin(), m_contextIconSizes.cend(), [this](const ContextIconInfo &info) {
702  return info.iconSize == q->iconSize().width();
703  });
704  if (it != m_contextIconSizes.cend()) {
705  it->iconAction->setChecked(true);
706  }
707 
708  switch (q->mainWindow()->toolBarArea(q)) {
710  contextBottom->setChecked(true);
711  break;
712  case Qt::LeftToolBarArea:
713  contextLeft->setChecked(true);
714  break;
716  contextRight->setChecked(true);
717  break;
718  default:
719  case Qt::TopToolBarArea:
720  contextTop->setChecked(true);
721  break;
722  }
723 
724  const bool showButtonSettings = contextButtonAction //
725  && !contextShowText->text().isEmpty() //
726  && contextTextRight->isChecked();
727  contextButtonTitle->setVisible(showButtonSettings);
728  contextShowText->setVisible(showButtonSettings);
729  if (showButtonSettings) {
730  contextShowText->setChecked(contextButtonAction->priority() >= QAction::NormalPriority);
731  }
732 }
733 
734 void KToolBarPrivate::slotContextAboutToHide()
735 {
736  // We have to unplug whatever slotContextAboutToShow plugged into the menu.
737  // Unplug the toolbar menu action
738  KXmlGuiWindow *kmw = qobject_cast<KXmlGuiWindow *>(q->mainWindow());
739  if (kmw && kmw->toolBarMenuAction()) {
740  if (kmw->toolBarMenuAction()->associatedWidgets().count() > 1) {
741  context->removeAction(kmw->toolBarMenuAction());
742  }
743  }
744 
745  // Unplug the configure toolbars action too, since it's afterwards anyway
746  QAction *configureAction = nullptr;
748  configureAction = findAction(QLatin1String(actionName));
749 
750  if (!configureAction && kmw) {
751  configureAction = kmw->actionCollection()->action(QLatin1String(actionName));
752  }
753 
754  if (configureAction) {
755  context->removeAction(configureAction);
756  }
757 
758  context->removeAction(contextLockAction);
759 }
760 
761 void KToolBarPrivate::slotContextLeft()
762 {
764 }
765 
766 void KToolBarPrivate::slotContextRight()
767 {
769 }
770 
771 void KToolBarPrivate::slotContextShowText()
772 {
773  Q_ASSERT(contextButtonAction);
774  const QAction::Priority priority = contextShowText->isChecked() ? QAction::NormalPriority : QAction::LowPriority;
775  contextButtonAction->setPriority(priority);
776 
777  // Find to which xml file and componentData the action belongs to
778  QString componentName;
779  QString filename;
780  KXMLGUIClient *client;
781  if (findAction(contextButtonAction->objectName(), &client)) {
782  componentName = client->componentName();
783  filename = client->xmlFile();
784  }
785  if (filename.isEmpty()) {
786  componentName = QCoreApplication::applicationName();
787  filename = componentName + QLatin1String("ui.rc");
788  }
789 
790  // Save the priority state of the action
791  const QString configFile = KXMLGUIFactory::readConfigFile(filename, componentName);
792 
793  QDomDocument document;
794  document.setContent(configFile);
796  QDomElement actionElem = KXMLGUIFactory::findActionByName(elem, contextButtonAction->objectName(), true);
797  actionElem.setAttribute(QStringLiteral("priority"), priority);
798  KXMLGUIFactory::saveConfigFile(document, filename, componentName);
799 }
800 
801 void KToolBarPrivate::slotContextTop()
802 {
804 }
805 
806 void KToolBarPrivate::slotContextBottom()
807 {
809 }
810 
811 void KToolBarPrivate::slotContextIcons()
812 {
814  toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle();
815 }
816 
817 void KToolBarPrivate::slotContextText()
818 {
820  toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle();
821 }
822 
823 void KToolBarPrivate::slotContextTextUnder()
824 {
826  toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle();
827 }
828 
829 void KToolBarPrivate::slotContextTextRight()
830 {
832  toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle();
833 }
834 
835 void KToolBarPrivate::slotContextIconSize(QAction *action)
836 {
837  if (action) {
838  auto it = std::find_if(m_contextIconSizes.cbegin(), m_contextIconSizes.cend(), [action](const ContextIconInfo &info) {
839  return info.iconAction == action;
840  });
841  if (it != m_contextIconSizes.cend()) {
842  q->setIconDimensions(it->iconSize);
843  }
844  }
845 }
846 
847 void KToolBarPrivate::slotLockToolBars(bool lock)
848 {
849  q->setToolBarsLocked(lock);
850 }
851 
852 KToolBar::KToolBar(QWidget *parent, bool isMainToolBar, bool readConfig)
853  : QToolBar(parent)
854  , d(new KToolBarPrivate(this))
855 {
856  d->init(readConfig, isMainToolBar);
857 
858  // KToolBar is auto-added to the top area of the main window if parent is a QMainWindow
859  if (QMainWindow *mw = qobject_cast<QMainWindow *>(parent)) {
860  mw->addToolBar(this);
861  }
862 }
863 
864 KToolBar::KToolBar(const QString &objectName, QWidget *parent, bool readConfig)
865  : QToolBar(parent)
866  , d(new KToolBarPrivate(this))
867 {
869  // mainToolBar -> isMainToolBar = true -> buttonStyle is configurable
870  // others -> isMainToolBar = false -> ### hardcoded default for buttonStyle !!! should be configurable? -> hidden key added
871  d->init(readConfig, (objectName == QLatin1String("mainToolBar")));
872 
873  // KToolBar is auto-added to the top area of the main window if parent is a QMainWindow
874  if (QMainWindow *mw = qobject_cast<QMainWindow *>(parent)) {
875  mw->addToolBar(this);
876  }
877 }
878 
879 KToolBar::KToolBar(const QString &objectName, QMainWindow *parent, Qt::ToolBarArea area, bool newLine, bool isMainToolBar, bool readConfig)
880  : QToolBar(parent)
881  , d(new KToolBarPrivate(this))
882 {
884  d->init(readConfig, isMainToolBar);
885 
886  if (newLine) {
887  mainWindow()->addToolBarBreak(area);
888  }
889 
890  mainWindow()->addToolBar(area, this);
891 
892  if (newLine) {
893  mainWindow()->addToolBarBreak(area);
894  }
895 }
896 
898 {
899  delete d->contextLockAction;
900 }
901 
902 #if KXMLGUI_BUILD_DEPRECATED_SINCE(5, 0)
904 {
905  d->enableContext = enable;
906 }
907 #endif
908 
909 #if KXMLGUI_BUILD_DEPRECATED_SINCE(5, 0)
911 {
912  return d->enableContext;
913 }
914 #endif
915 
917 {
918  Q_ASSERT(!cg.name().isEmpty());
919 
920  const int currentIconSize = iconSize().width();
921  // qCDebug(DEBUG_KXMLGUI) << objectName() << currentIconSize << d->iconSizeSettings.toString() << "defaultValue=" << d->iconSizeSettings.defaultValue();
922  if (!cg.hasDefault("IconSize") && currentIconSize == d->iconSizeSettings.defaultValue()) {
923  cg.revertToDefault("IconSize");
924  d->iconSizeSettings[Level_UserSettings] = Unset;
925  } else {
926  cg.writeEntry("IconSize", currentIconSize);
927  d->iconSizeSettings[Level_UserSettings] = currentIconSize;
928  }
929 
930  const Qt::ToolButtonStyle currentToolButtonStyle = toolButtonStyle();
931  if (!cg.hasDefault("ToolButtonStyle") && currentToolButtonStyle == d->toolButtonStyleSettings.defaultValue()) {
932  cg.revertToDefault("ToolButtonStyle");
933  d->toolButtonStyleSettings[Level_UserSettings] = Unset;
934  } else {
935  cg.writeEntry("ToolButtonStyle", d->toolButtonStyleToString(currentToolButtonStyle));
936  d->toolButtonStyleSettings[Level_UserSettings] = currentToolButtonStyle;
937  }
938 }
939 
940 #if KXMLGUI_BUILD_DEPRECATED_SINCE(5, 0)
942 {
943  d->xmlguiClients.clear();
944  d->xmlguiClients << client;
945 }
946 #endif
947 
949 {
950  d->xmlguiClients << client;
951 }
952 
954 {
955  d->xmlguiClients.remove(client);
956 }
957 
958 void KToolBar::contextMenuEvent(QContextMenuEvent *event)
959 {
960 #if KXMLGUI_BUILD_DEPRECATED_SINCE(5, 0)
961  if (mainWindow() && d->enableContext) {
962  QPointer<KToolBar> guard(this);
963  const QPoint globalPos = event->globalPos();
964  d->contextMenu(globalPos)->exec(globalPos);
965 
966  // "Configure Toolbars" recreates toolbars, so we might not exist anymore.
967  if (guard) {
968  d->slotContextAboutToHide();
969  }
970  return;
971  }
972 #endif
973 
975 }
976 
977 void KToolBar::loadState(const QDomElement &element)
978 {
979  QMainWindow *mw = mainWindow();
980  if (!mw) {
981  return;
982  }
983 
984  {
985  const QString &i18nText = KToolbarHelper::i18nToolBarName(element);
986  if (!i18nText.isEmpty()) {
987  setWindowTitle(i18nText);
988  }
989  }
990 
991  /*
992  This method is called in order to load toolbar settings from XML.
993  However this can be used in two rather different cases:
994  - for the initial loading of the app's XML. In that case the settings
995  are only the defaults (Level_AppXML), the user's KConfig settings will override them
996 
997  - for later re-loading when switching between parts in KXMLGUIFactory.
998  In that case the XML contains the final settings, not the defaults.
999  We do need the defaults, and the toolbar might have been completely
1000  deleted and recreated meanwhile. So we store the app-default settings
1001  into the XML.
1002  */
1003  bool loadingAppDefaults = true;
1004  if (element.hasAttribute(QStringLiteral("tempXml"))) {
1005  // this isn't the first time, so the app-xml defaults have been saved into the (in-memory) XML
1006  loadingAppDefaults = false;
1007  const QString iconSizeDefault = element.attribute(QStringLiteral("iconSizeDefault"));
1008  if (!iconSizeDefault.isEmpty()) {
1009  d->iconSizeSettings[Level_AppXML] = iconSizeDefault.toInt();
1010  }
1011  const QString toolButtonStyleDefault = element.attribute(QStringLiteral("toolButtonStyleDefault"));
1012  if (!toolButtonStyleDefault.isEmpty()) {
1013  d->toolButtonStyleSettings[Level_AppXML] = d->toolButtonStyleFromString(toolButtonStyleDefault);
1014  }
1015  } else {
1016  // loading app defaults
1017  bool newLine = false;
1018  QString attrNewLine = element.attribute(QStringLiteral("newline")).toLower();
1019  if (!attrNewLine.isEmpty()) {
1020  newLine = (attrNewLine == QLatin1String("true"));
1021  }
1022  if (newLine && mw) {
1023  mw->insertToolBarBreak(this);
1024  }
1025  }
1026 
1027  int newIconSize = -1;
1028  if (element.hasAttribute(QStringLiteral("iconSize"))) {
1029  bool ok;
1030  newIconSize = element.attribute(QStringLiteral("iconSize")).trimmed().toInt(&ok);
1031  if (!ok) {
1032  newIconSize = -1;
1033  }
1034  }
1035  if (newIconSize != -1) {
1036  d->iconSizeSettings[loadingAppDefaults ? Level_AppXML : Level_UserSettings] = newIconSize;
1037  }
1038 
1039  const QString newToolButtonStyle = element.attribute(QStringLiteral("iconText"));
1040  if (!newToolButtonStyle.isEmpty()) {
1041  d->toolButtonStyleSettings[loadingAppDefaults ? Level_AppXML : Level_UserSettings] = d->toolButtonStyleFromString(newToolButtonStyle);
1042  }
1043 
1044  bool hidden = false;
1045  {
1046  QString attrHidden = element.attribute(QStringLiteral("hidden")).toLower();
1047  if (!attrHidden.isEmpty()) {
1048  hidden = (attrHidden == QLatin1String("true"));
1049  }
1050  }
1051 
1053  {
1054  QString attrPosition = element.attribute(QStringLiteral("position")).toLower();
1055  if (!attrPosition.isEmpty()) {
1056  pos = KToolBarPrivate::positionFromString(attrPosition);
1057  }
1058  }
1059  if (pos != Qt::NoToolBarArea) {
1060  mw->addToolBar(pos, this);
1061  }
1062 
1063  setVisible(!hidden);
1064 
1065  d->applyCurrentSettings();
1066 }
1067 
1068 // Called when switching between xmlgui clients, in order to find any unsaved settings
1069 // again when switching back to the current xmlgui client.
1070 void KToolBar::saveState(QDomElement &current) const
1071 {
1072  Q_ASSERT(!current.isNull());
1073 
1074  current.setAttribute(QStringLiteral("tempXml"), QStringLiteral("true"));
1075 
1076  current.setAttribute(QStringLiteral("noMerge"), QStringLiteral("1"));
1077  current.setAttribute(QStringLiteral("position"), d->getPositionAsString().toLower());
1078  current.setAttribute(QStringLiteral("hidden"), isHidden() ? QStringLiteral("true") : QStringLiteral("false"));
1079 
1080  const int currentIconSize = iconSize().width();
1081  if (currentIconSize == d->iconSizeSettings.defaultValue()) {
1082  current.removeAttribute(QStringLiteral("iconSize"));
1083  } else {
1084  current.setAttribute(QStringLiteral("iconSize"), iconSize().width());
1085  }
1086 
1087  if (toolButtonStyle() == d->toolButtonStyleSettings.defaultValue()) {
1088  current.removeAttribute(QStringLiteral("iconText"));
1089  } else {
1090  current.setAttribute(QStringLiteral("iconText"), d->toolButtonStyleToString(toolButtonStyle()));
1091  }
1092 
1093  // Note: if this method is used by more than KXMLGUIBuilder, e.g. to save XML settings to *disk*,
1094  // then the stuff below shouldn't always be done. This is not the case currently though.
1095  if (d->iconSizeSettings[Level_AppXML] != Unset) {
1096  current.setAttribute(QStringLiteral("iconSizeDefault"), d->iconSizeSettings[Level_AppXML]);
1097  }
1098  if (d->toolButtonStyleSettings[Level_AppXML] != Unset) {
1099  const Qt::ToolButtonStyle bs = static_cast<Qt::ToolButtonStyle>(d->toolButtonStyleSettings[Level_AppXML]);
1100  current.setAttribute(QStringLiteral("toolButtonStyleDefault"), d->toolButtonStyleToString(bs));
1101  }
1102 }
1103 
1104 // called by KMainWindow::applyMainWindowSettings to read from the user settings
1106 {
1107  Q_ASSERT(!cg.name().isEmpty());
1108 
1109  if (cg.hasKey("IconSize")) {
1110  d->iconSizeSettings[Level_UserSettings] = cg.readEntry("IconSize", 0);
1111  }
1112  if (cg.hasKey("ToolButtonStyle")) {
1113  d->toolButtonStyleSettings[Level_UserSettings] = d->toolButtonStyleFromString(cg.readEntry("ToolButtonStyle", QString()));
1114  }
1115 
1116  d->applyCurrentSettings();
1117 }
1118 
1120 {
1121  return qobject_cast<KMainWindow *>(const_cast<QObject *>(parent()));
1122 }
1123 
1125 {
1127  d->iconSizeSettings[Level_UserSettings] = size;
1128 }
1129 
1131 {
1133 }
1134 
1135 void KToolBar::slotMovableChanged(bool movable)
1136 {
1137  if (movable && !KAuthorized::authorize(QStringLiteral("movable_toolbars"))) {
1138  setMovable(false);
1139  }
1140 }
1141 
1142 void KToolBar::dragEnterEvent(QDragEnterEvent *event)
1143 {
1144  if (toolBarsEditable() && event->proposedAction() & (Qt::CopyAction | Qt::MoveAction)
1145  && event->mimeData()->hasFormat(QStringLiteral("application/x-kde-action-list"))) {
1146  QByteArray data = event->mimeData()->data(QStringLiteral("application/x-kde-action-list"));
1147 
1148  QDataStream stream(data);
1149 
1150  QStringList actionNames;
1151 
1152  stream >> actionNames;
1153 
1154  const auto allCollections = KActionCollection::allCollections();
1155  for (const QString &actionName : std::as_const(actionNames)) {
1156  for (KActionCollection *ac : allCollections) {
1157  QAction *newAction = ac->action(actionName);
1158  if (newAction) {
1159  d->actionsBeingDragged.append(newAction);
1160  break;
1161  }
1162  }
1163  }
1164 
1165  if (!d->actionsBeingDragged.isEmpty()) {
1166  QAction *overAction = actionAt(event->pos());
1167 
1168  QFrame *dropIndicatorWidget = new QFrame(this);
1169  dropIndicatorWidget->resize(8, height() - 4);
1170  dropIndicatorWidget->setFrameShape(QFrame::VLine);
1171  dropIndicatorWidget->setLineWidth(3);
1172 
1173  d->dropIndicatorAction = insertWidget(overAction, dropIndicatorWidget);
1174 
1175  insertAction(overAction, d->dropIndicatorAction);
1176 
1177  event->acceptProposedAction();
1178  return;
1179  }
1180  }
1181 
1183 }
1184 
1185 void KToolBar::dragMoveEvent(QDragMoveEvent *event)
1186 {
1187  if (toolBarsEditable()) {
1188  Q_FOREVER {
1189  if (d->dropIndicatorAction) {
1190  QAction *overAction = nullptr;
1191  const auto actions = this->actions();
1192  for (QAction *action : actions) {
1193  // want to make it feel that half way across an action you're dropping on the other side of it
1194  QWidget *widget = widgetForAction(action);
1195  if (event->pos().x() < widget->pos().x() + (widget->width() / 2)) {
1196  overAction = action;
1197  break;
1198  }
1199  }
1200 
1201  if (overAction != d->dropIndicatorAction) {
1202  // Check to see if the indicator is already in the right spot
1203  int dropIndicatorIndex = actions.indexOf(d->dropIndicatorAction);
1204  if (dropIndicatorIndex + 1 < actions.count()) {
1205  if (actions.at(dropIndicatorIndex + 1) == overAction) {
1206  break;
1207  }
1208  } else if (!overAction) {
1209  break;
1210  }
1211 
1212  insertAction(overAction, d->dropIndicatorAction);
1213  }
1214 
1215  event->accept();
1216  return;
1217  }
1218  break;
1219  }
1220  }
1221 
1223 }
1224 
1225 void KToolBar::dragLeaveEvent(QDragLeaveEvent *event)
1226 {
1227  // Want to clear this even if toolBarsEditable was changed mid-drag (unlikely)
1228  delete d->dropIndicatorAction;
1229  d->dropIndicatorAction = nullptr;
1230  d->actionsBeingDragged.clear();
1231 
1232  if (toolBarsEditable()) {
1233  event->accept();
1234  return;
1235  }
1236 
1238 }
1239 
1240 void KToolBar::dropEvent(QDropEvent *event)
1241 {
1242  if (toolBarsEditable()) {
1243  for (QAction *action : std::as_const(d->actionsBeingDragged)) {
1244  if (actions().contains(action)) {
1245  removeAction(action);
1246  }
1247  insertAction(d->dropIndicatorAction, action);
1248  }
1249  }
1250 
1251  // Want to clear this even if toolBarsEditable was changed mid-drag (unlikely)
1252  delete d->dropIndicatorAction;
1253  d->dropIndicatorAction = nullptr;
1254  d->actionsBeingDragged.clear();
1255 
1256  if (toolBarsEditable()) {
1257  event->accept();
1258  return;
1259  }
1260 
1262 }
1263 
1264 void KToolBar::mousePressEvent(QMouseEvent *event)
1265 {
1266  if (toolBarsEditable() && event->button() == Qt::LeftButton) {
1267  if (QAction *action = actionAt(event->pos())) {
1268  d->dragAction = action;
1269  d->dragStartPosition = event->pos();
1270  event->accept();
1271  return;
1272  }
1273  }
1274 
1276 }
1277 
1278 void KToolBar::mouseMoveEvent(QMouseEvent *event)
1279 {
1280  if (!toolBarsEditable() || !d->dragAction) {
1282  return;
1283  }
1284 
1285  if ((event->pos() - d->dragStartPosition).manhattanLength() < QApplication::startDragDistance()) {
1286  event->accept();
1287  return;
1288  }
1289 
1290  QDrag *drag = new QDrag(this);
1291  QMimeData *mimeData = new QMimeData;
1292 
1293  QByteArray data;
1294  {
1295  QDataStream stream(&data, QIODevice::WriteOnly);
1296 
1297  QStringList actionNames;
1298  actionNames << d->dragAction->objectName();
1299 
1300  stream << actionNames;
1301  }
1302 
1303  mimeData->setData(QStringLiteral("application/x-kde-action-list"), data);
1304 
1305  drag->setMimeData(mimeData);
1306 
1307  Qt::DropAction dropAction = drag->exec(Qt::MoveAction);
1308 
1309  if (dropAction == Qt::MoveAction) {
1310  // Only remove from this toolbar if it was moved to another toolbar
1311  // Otherwise the receiver moves it.
1312  if (drag->target() != this) {
1313  removeAction(d->dragAction);
1314  }
1315  }
1316 
1317  d->dragAction = nullptr;
1318  event->accept();
1319 }
1320 
1321 void KToolBar::mouseReleaseEvent(QMouseEvent *event)
1322 {
1323  // Want to clear this even if toolBarsEditable was changed mid-drag (unlikely)
1324  if (d->dragAction) {
1325  d->dragAction = nullptr;
1326  event->accept();
1327  return;
1328  }
1329 
1331 }
1332 
1333 bool KToolBar::eventFilter(QObject *watched, QEvent *event)
1334 {
1335  // Generate context menu events for disabled buttons too...
1336  if (event->type() == QEvent::MouseButtonPress) {
1337  QMouseEvent *me = static_cast<QMouseEvent *>(event);
1338  if (me->buttons() & Qt::RightButton) {
1339  if (QWidget *ww = qobject_cast<QWidget *>(watched)) {
1340  if (ww->parent() == this && !ww->isEnabled()) {
1342  }
1343  }
1344  }
1345 
1346  } else if (event->type() == QEvent::ParentChange) {
1347  // Make sure we're not leaving stale event filters around,
1348  // when a child is reparented somewhere else
1349  if (QWidget *ww = qobject_cast<QWidget *>(watched)) {
1350  if (!this->isAncestorOf(ww)) {
1351  // New parent is not a subwidget - remove event filter
1352  ww->removeEventFilter(this);
1353  const auto children = ww->findChildren<QWidget *>();
1354  for (QWidget *child : children) {
1355  child->removeEventFilter(this);
1356  }
1357  }
1358  }
1359  }
1360 
1361  // Redirect mouse events to the toolbar when drag + drop editing is enabled
1362  if (toolBarsEditable()) {
1363  if (QWidget *ww = qobject_cast<QWidget *>(watched)) {
1364  switch (event->type()) {
1365  case QEvent::MouseButtonPress: {
1366  QMouseEvent *me = static_cast<QMouseEvent *>(event);
1367  QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(), me->button(), me->buttons(), me->modifiers());
1368  mousePressEvent(&newEvent);
1369  return true;
1370  }
1371  case QEvent::MouseMove: {
1372  QMouseEvent *me = static_cast<QMouseEvent *>(event);
1373  QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(), me->button(), me->buttons(), me->modifiers());
1374  mouseMoveEvent(&newEvent);
1375  return true;
1376  }
1378  QMouseEvent *me = static_cast<QMouseEvent *>(event);
1379  QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(), me->button(), me->buttons(), me->modifiers());
1380  mouseReleaseEvent(&newEvent);
1381  return true;
1382  }
1383  default:
1384  break;
1385  }
1386  }
1387  }
1388 
1389  return QToolBar::eventFilter(watched, event);
1390 }
1391 
1392 void KToolBar::actionEvent(QActionEvent *event)
1393 {
1394  if (event->type() == QEvent::ActionRemoved) {
1395  QWidget *widget = widgetForAction(event->action());
1396  if (widget) {
1397  widget->removeEventFilter(this);
1398 
1399  const auto children = widget->findChildren<QWidget *>();
1400  for (QWidget *child : children) {
1401  child->removeEventFilter(this);
1402  }
1403  }
1404  }
1405 
1407 
1408  if (event->type() == QEvent::ActionAdded) {
1409  QWidget *widget = widgetForAction(event->action());
1410  if (widget) {
1411  widget->installEventFilter(this);
1412 
1413  const auto children = widget->findChildren<QWidget *>();
1414  for (QWidget *child : children) {
1415  child->installEventFilter(this);
1416  }
1417  // Center widgets that do not have any use for more space. See bug 165274
1418  if (!(widget->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag)
1419  // ... but do not center when using text besides icon in vertical toolbar. See bug 243196
1421  const int index = layout()->indexOf(widget);
1422  if (index != -1) {
1424  }
1425  }
1426  }
1427  }
1428 
1429  d->adjustSeparatorVisibility();
1430 }
1431 
1433 {
1434  return KToolBarPrivate::s_editable;
1435 }
1436 
1438 {
1439  if (KToolBarPrivate::s_editable != editable) {
1440  KToolBarPrivate::s_editable = editable;
1441  }
1442 }
1443 
1445 {
1446  if (KToolBarPrivate::s_locked != locked) {
1447  KToolBarPrivate::s_locked = locked;
1448 
1449  const auto windows = KMainWindow::memberList();
1450  for (KMainWindow *mw : windows) {
1451  const auto toolbars = mw->findChildren<KToolBar *>();
1452  for (KToolBar *toolbar : toolbars) {
1453  toolbar->d->setLocked(locked);
1454  }
1455  }
1456  }
1457 }
1458 
1460 {
1461  return KToolBarPrivate::s_locked;
1462 }
1463 
1465 {
1466 #ifdef QT_DBUS_LIB
1467  QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KToolBar"), QStringLiteral("org.kde.KToolBar"), QStringLiteral("styleChanged"));
1469 #endif
1470 }
1471 
1472 #include "moc_ktoolbar.cpp"
void removeEventFilter(QObject *obj)
static bool toolBarsEditable()
Returns whether the toolbars are currently editable (drag & drop of actions).
Definition: ktoolbar.cpp:1432
bool eventFilter(QObject *watched, QEvent *event) override
Reimplemented to support context menu activation on disabled tool buttons.
Definition: ktoolbar.cpp:1333
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
void setSettingsDirty()
Tell the main window that it should save its settings when being closed.
QPoint pos() const const
virtual QLayoutItem * itemAt(int index) const const=0
QString readEntry(const char *key, const char *aDefault=nullptr) const
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
AlignJustify
virtual void contextMenuEvent(QContextMenuEvent *event)
QList< QAction * > actions() const const
MouseButtonPress
QList< int > querySizes(KIconLoader::Group group) const
QString number(int n, int base)
void iconSizeChanged(const QSize &iconSize)
void setAlignment(Qt::Alignment alignment)
void setContextMenuEnabled(bool enable=true)
This allows you to enable or disable the context menu.
Definition: ktoolbar.cpp:903
void setData(const QString &mimeType, const QByteArray &data)
static QList< KMainWindow * > memberList()
Qt::MouseButton button() const const
static bool saveConfigFile(const QDomDocument &doc, const QString &filename, const QString &componentName=QString())
QCA_EXPORT void init()
virtual void actionEvent(QActionEvent *event) override
int count(const T &value) const const
static void setGlobalDefaultToolBar(const char *toolBarName)
Sets the default toolbar which will be auto-selected for all KEditToolBar instances.
QLayout * layout() const const
void setupToolbarMenuActions()
bool isNull() const const
bool isAncestorOf(const QWidget *child) const const
QPoint mapFromGlobal(const QPoint &pos) const const
QIcon fromTheme(const QString &name)
QStringView level(QStringView ifopt)
static const QList< KActionCollection * > & allCollections()
Access the list of all action collections in existence for this app.
QList< QWidget * > associatedWidgets() const const
void insertToolBarBreak(QToolBar *before)
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QAction * insertWidget(QAction *before, QWidget *widget)
QAction * toolBarMenuAction()
virtual void dropEvent(QDropEvent *event)
void setFrameShape(QFrame::Shape)
LeftButton
Floatable toolbar with auto resize.
Definition: ktoolbar.h:67
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
void removeXMLGUIClient(KXMLGUIClient *client)
Removes an XML gui client that uses this toolbar.
Definition: ktoolbar.cpp:953
Qt::DropAction exec(Qt::DropActions supportedActions)
void insertAction(QAction *before, QAction *action)
QAction * toggleViewAction() const const
void removeAttribute(const QString &name)
A container for a set of QAction objects.
bool send(const QDBusMessage &message) const const
QAction * addAction(const QString &text)
void setAttribute(const QString &name, const QString &value)
virtual bool eventFilter(QObject *watched, QEvent *event)
virtual void setVisible(bool visible)
QMenu * menu() const const
void setIcon(const QIcon &icon)
static QDomElement findActionByName(QDomElement &elem, const QString &sName, bool create)
QString i18n(const char *text, const TYPE &arg...)
QDBusConnection sessionBus()
static QString readConfigFile(const QString &filename, const QString &componentName=QString())
void saveSettings(KConfigGroup &cg)
Save the toolbar settings to group cg.
Definition: ktoolbar.cpp:916
virtual QString xmlFile() const
This will return the name of the XML file as set by setXMLFile().
void toggled(bool checked)
KCONFIGCORE_EXPORT bool authorizeAction(const QString &action)
void setIconSize(const QSize &iconSize)
void setLineWidth(int)
KToolBar(QWidget *parent, bool isMainToolBar=false, bool readConfig=true)
Constructor.
Definition: ktoolbar.cpp:852
int indexOf(const T &value, int from) const const
void installEventFilter(QObject *filterObj)
Vertical
bool isEmpty() const const
Qt::MouseButtons buttons() const const
QList< T > findChildren(const QString &name, Qt::FindChildOptions options) const const
void addToolBar(Qt::ToolBarArea area, QToolBar *toolbar)
ToolBarArea
void setWindowTitle(const QString &)
void saveState(QDomElement &element) const
Save state into an XML.
Definition: ktoolbar.cpp:1070
void setIconDimensions(int size)
Convenience function to set icon size.
Definition: ktoolbar.cpp:1124
const T & at(int i) const const
static KIconLoader * global()
void setMovable(bool movable)
QAction * action(int index) const
Return the QAction* at position index in the action collection.
void movableChanged(bool movable)
void setText(const QString &text)
int toInt(bool *ok, int base) const const
void addToolBarBreak(Qt::ToolBarArea area)
bool isEmpty() const const
static void setToolBarsEditable(bool editable)
Enable or disable toolbar editing via drag & drop of actions.
Definition: ktoolbar.cpp:1437
static void emitToolbarStyleChanged()
Emits a D-Bus signal to tell all toolbars in all applications, that the user settings have changed.
Definition: ktoolbar.cpp:1464
void addXMLGUIClient(KXMLGUIClient *client)
Adds an XML gui client that uses this toolbar.
Definition: ktoolbar.cpp:948
void setAcceptDrops(bool on)
bool hasKey(const char *key) const
QDBusMessage createSignal(const QString &path, const QString &interface, const QString &name)
virtual int indexOf(QWidget *widget) const const
void setXMLGUIClient(KXMLGUIClient *client)
Sets the XML gui client.
Definition: ktoolbar.cpp:941
void setCheckable(bool)
int currentSize(KIconLoader::Group group) const
KCONFIGCORE_EXPORT bool authorize(const QString &action)
void removeAction(QAction *action)
Qt::KeyboardModifiers modifiers() const const
virtual void mouseReleaseEvent(QMouseEvent *event)
void loadState(const QDomElement &element)
Load state from an XML.
Definition: ktoolbar.cpp:977
void setVisible(bool)
static bool toolBarsLocked()
Returns whether the toolbars are locked (i.e., moving of the toobars disallowed).
Definition: ktoolbar.cpp:1459
void revertToDefault(const char *key)
KMainWindow with convenience functions and integration with XmlGui files.
Definition: kxmlguiwindow.h:87
QString toLower() const const
CopyAction
void resize(int w, int h)
bool hasAttribute(const QString &name) const const
void triggered(bool checked)
~KToolBar() override
Destroys the toolbar.
Definition: ktoolbar.cpp:897
virtual void dragLeaveEvent(QDragLeaveEvent *event)
void iconLoaderSettingsChanged()
QAction * actionAt(const QPoint &p) const const
virtual KActionCollection * actionCollection() const
Retrieves the entire action collection for the GUI client.
bool hasDefault(const char *key) const
void setEnabled(bool)
void toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle)
KMainWindow represents a top-level main window.
Definition: kmainwindow.h:69
void postEvent(QObject *receiver, QEvent *event, int priority)
static void setToolBarsLocked(bool locked)
Allows you to lock and unlock all toolbars (i.e., disallow/allow moving of the toobars).
Definition: ktoolbar.cpp:1444
void allowedAreasChanged(Qt::ToolBarAreas allowedAreas)
QEvent::Type type() const const
QObject * target() const const
QPoint globalPos() const const
const char * name(StandardAction id)
void orientationChanged(Qt::Orientation orientation)
virtual bool event(QEvent *event) override
void setToolButtonStyle(Qt::ToolButtonStyle toolButtonStyle)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
ToolButtonStyle
QList::iterator begin()
static QDomElement actionPropertiesElement(QDomDocument &doc)
bool contextMenuEnabled() const
Returns the context menu enabled flag.
Definition: ktoolbar.cpp:910
QString name() const
QWidget * widgetForAction(QAction *action) const const
QString attribute(const QString &name, const QString &defValue) const const
bool isHidden() const const
void setMimeData(QMimeData *data)
QAction * menuAction() const const
void setChecked(bool)
QList::iterator end()
virtual void mouseMoveEvent(QMouseEvent *event)
KMainWindow * mainWindow() const
Returns the main window that this toolbar is docked with.
Definition: ktoolbar.cpp:1119
QVector< V > values(const QMultiHash< K, V > &c)
QObject * parent() const const
KIconTheme * theme() const
QString message
WA_DeleteOnClose
Qt::ToolBarArea toolBarArea(QToolBar *toolbar) const const
void applySettings(const KConfigGroup &cg)
Read the toolbar settings from group cg and apply them.
Definition: ktoolbar.cpp:1105
char * data()
bool isSeparator() const const
void aboutToShow()
const QObjectList & children() const const
virtual void dragEnterEvent(QDragEnterEvent *event)
char * toString(const EngineQuery &query)
virtual void mousePressEvent(QMouseEvent *event)
virtual QString componentName() const
int iconSizeDefault() const
Returns the default size for this type of toolbar.
Definition: ktoolbar.cpp:1130
virtual void dragMoveEvent(QDragMoveEvent *event)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Dec 5 2023 04:05:20 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.