KXmlGui

kmainwindow.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2000 Reginald Stadlbauer <[email protected]>
4  SPDX-FileCopyrightText: 1997 Stephan Kulow <[email protected]>
5  SPDX-FileCopyrightText: 1997-2000 Sven Radej <[email protected]>
6  SPDX-FileCopyrightText: 1997-2000 Matthias Ettrich <[email protected]>
7  SPDX-FileCopyrightText: 1999 Chris Schlaeger <[email protected]>
8  SPDX-FileCopyrightText: 2002 Joseph Wenninger <[email protected]>
9  SPDX-FileCopyrightText: 2005-2006 Hamish Rodda <[email protected]>
10  SPDX-FileCopyrightText: 2000-2008 David Faure <[email protected]>
11 
12  SPDX-License-Identifier: LGPL-2.0-only
13 */
14 
15 #include "kmainwindow.h"
16 
17 #include "kmainwindow_p.h"
18 #ifdef QT_DBUS_LIB
19 #include "kmainwindowiface_p.h"
20 #endif
21 #include "ktoolbarhandler_p.h"
22 #include "khelpmenu.h"
23 #include "ktoolbar.h"
24 
25 #include <QApplication>
26 #include <QList>
27 #include <QObject>
28 #include <QTimer>
29 #include <QCloseEvent>
30 #include <QDockWidget>
31 #include <QMenuBar>
32 #include <QSessionManager>
33 #include <QStatusBar>
34 #include <QStyle>
35 #include <QWidget>
36 #include <QWindow>
37 #ifdef QT_DBUS_LIB
38 #include <QDBusConnection>
39 #endif
40 
41 #include <ktoggleaction.h>
42 #include <kaboutdata.h>
43 #include <kconfig.h>
44 #include <ksharedconfig.h>
45 #include <klocalizedstring.h>
46 #include <kconfiggroup.h>
47 #include <kwindowconfig.h>
48 #include <kconfiggui.h>
49 
50 //#include <ctype.h>
51 
52 static const char WINDOW_PROPERTIES[]="WindowProperties";
53 
54 static QMenuBar *internalMenuBar(KMainWindow *mw)
55 {
57 }
58 
59 static QStatusBar *internalStatusBar(KMainWindow *mw)
60 {
62 }
63 
72 class DockResizeListener : public QObject
73 {
74  Q_OBJECT
75 public:
76  DockResizeListener(KMainWindow *win);
77  ~DockResizeListener() override;
78  bool eventFilter(QObject *watched, QEvent *event) override;
79 
80 private:
81  KMainWindow *m_win;
82 };
83 
84 DockResizeListener::DockResizeListener(KMainWindow *win) :
85  QObject(win),
86  m_win(win)
87 {
88 }
89 
90 DockResizeListener::~DockResizeListener()
91 {
92 }
93 
94 bool DockResizeListener::eventFilter(QObject *watched, QEvent *event)
95 {
96  switch (event->type()) {
97  case QEvent::Resize:
98  case QEvent::Move:
99  case QEvent::Show:
100  case QEvent::Hide:
101  m_win->k_ptr->setSettingsDirty(KMainWindowPrivate::CompressCalls);
102  break;
103 
104  default:
105  break;
106  }
107 
108  return QObject::eventFilter(watched, event);
109 }
110 
111 KMWSessionManager::KMWSessionManager()
112 {
114  this, &KMWSessionManager::saveState);
116  this, &KMWSessionManager::commitData);
117 }
118 
119 KMWSessionManager::~KMWSessionManager()
120 {
121 }
122 
123 void KMWSessionManager::saveState(QSessionManager &sm)
124 {
126 
128  const auto windows = KMainWindow::memberList();
129  if (!windows.isEmpty()) {
130  // According to Jochen Wilhelmy <[email protected]>, this
131  // hook is useful for better document orientation
132  windows.at(0)->saveGlobalProperties(config);
133  }
134 
135  int n = 0;
136  for (KMainWindow *mw : windows) {
137  n++;
138  mw->savePropertiesInternal(config, n);
139  }
140 
141  KConfigGroup group(config, "Number");
142  group.writeEntry("NumberOfWindows", n);
143 
144  // store new status to disk
145  config->sync();
146 
147  // generate discard command for new file
149  if (QFile::exists(localFilePath)) {
151  discard << QStringLiteral("rm");
152  discard << localFilePath;
153  sm.setDiscardCommand(discard);
154  }
155 }
156 
157 void KMWSessionManager::commitData(QSessionManager &sm)
158 {
159  if (!sm.allowsInteraction()) {
160  return;
161  }
162 
163  /*
164  Purpose of this exercise: invoke queryClose() without actually closing the
165  windows, because
166  - queryClose() may contain session management code, so it must be invoked
167  - actually closing windows may quit the application - cf.
168  QGuiApplication::quitOnLastWindowClosed()
169  - quitting the application and thus closing the session manager connection
170  violates the X11 XSMP protocol.
171  The exact requirement of XSMP that would be broken is,
172  in the description of the client's state machine:
173 
174  save-yourself-done: (changing state is forbidden)
175 
176  Closing the session manager connection causes a state change.
177  Worst of all, that is a real problem with ksmserver - it will not save
178  applications that quit on their own in state save-yourself-done.
179  */
180  const auto windows = KMainWindow::memberList();
181  for (KMainWindow *window : windows) {
183  continue;
184  }
185  QCloseEvent e;
187  if (!e.isAccepted()) {
188  sm.cancel();
189  return;
190  }
191  }
192 }
193 
194 Q_GLOBAL_STATIC(KMWSessionManager, ksm)
195 Q_GLOBAL_STATIC(QList<KMainWindow *>, sMemberList)
196 
197 KMainWindow::KMainWindow(QWidget *parent, Qt::WindowFlags f)
198  : QMainWindow(parent, f), k_ptr(new KMainWindowPrivate)
199 {
200  k_ptr->init(this);
201 }
202 
203 KMainWindow::KMainWindow(KMainWindowPrivate &dd, QWidget *parent, Qt::WindowFlags f)
204  : QMainWindow(parent, f), k_ptr(&dd)
205 {
206  k_ptr->init(this);
207 }
208 
209 void KMainWindowPrivate::init(KMainWindow *_q)
210 {
211  q = _q;
213  q->setAnimated(q->style()->styleHint(QStyle::SH_Widget_Animate, nullptr, q));
214 
215  q->setAttribute(Qt::WA_DeleteOnClose);
216 
217  helpMenu = nullptr;
218 
219  //actionCollection()->setWidget( this );
220 #if 0
221  QObject::connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)),
222  q, SLOT(_k_slotSettingsChanged(int)));
223 #endif
224 
225  // force KMWSessionManager creation
226  ksm();
227 
228  sMemberList()->append(q);
229 
230  // Set the icon theme fallback to breeze (if not already set)
231  // Most of our apps use "lots" of icons that most of the times
232  // are only available with breeze, we still honour the user icon
233  // theme but if the icon is not found there, we go to breeze
234  // since it's almost sure it'll be there.
235  // This should be done as soon as possible (preferably via
236  // Q_COREAPP_STARTUP_FUNCTION), but as for now it cannot be done too soon
237  // as at that point QPlatformTheme is not instantiated yet and breaks the
238  // internal status of QIconLoader (see QTBUG-74252).
239  // See also discussion at https://phabricator.kde.org/D22488
240  // TODO: remove this once we depend on Qt 5.15.1, where this is fixed
241 #if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
242  if (QIcon::fallbackThemeName().isEmpty()) {
243  QIcon::setFallbackThemeName(QStringLiteral("breeze"));
244  }
245 #endif
246 
247  // If application is translated, load translator information for use in
248  // KAboutApplicationDialog or other getters. The context and messages below
249  // both must be exactly as listed, and are forced to be loaded from the
250  // application's own message catalog instead of kxmlgui's.
252  if (aboutData.translators().isEmpty()) {
253  aboutData.setTranslator(
254  i18ndc(nullptr, "NAME OF TRANSLATORS", "Your names"),
255  i18ndc(nullptr, "EMAIL OF TRANSLATORS", "Your emails"));
256 
258  }
259 
260  settingsDirty = false;
261  autoSaveSettings = false;
262  autoSaveWindowSize = true; // for compatibility
263  //d->kaccel = actionCollection()->kaccel();
264  settingsTimer = nullptr;
265  sizeTimer = nullptr;
266 
267  dockResizeListener = new DockResizeListener(_q);
268  letDirtySettings = true;
269 
270  sizeApplied = false;
271 }
272 
273 static bool endsWithHashNumber(const QString &s)
274 {
275  for (int i = s.length() - 1;
276  i > 0;
277  --i) {
278  if (s[ i ] == QLatin1Char('#') && i != s.length() - 1) {
279  return true; // ok
280  }
281  if (!s[ i ].isDigit()) {
282  break;
283  }
284  }
285  return false;
286 }
287 
288 static inline bool isValidDBusObjectPathCharacter(const QChar &c)
289 {
290  ushort u = c.unicode();
291  return (u >= QLatin1Char('a') && u <= QLatin1Char('z'))
292  || (u >= QLatin1Char('A') && u <= QLatin1Char('Z'))
293  || (u >= QLatin1Char('0') && u <= QLatin1Char('9'))
294  || (u == QLatin1Char('_')) || (u == QLatin1Char('/'));
295 }
296 
297 void KMainWindowPrivate::polish(KMainWindow *q)
298 {
299  // Set a unique object name. Required by session management, window management, and for the dbus interface.
300  QString objname;
301  QString s;
302  int unusedNumber = 1;
303  const QString name = q->objectName();
304  bool startNumberingImmediately = true;
305  bool tryReuse = false;
306  if (name.isEmpty()) {
307  // no name given
308  objname = QStringLiteral("MainWindow#");
309  } else if (name.endsWith(QLatin1Char('#'))) {
310  // trailing # - always add a number - KWin uses this for better grouping
311  objname = name;
312  } else if (endsWithHashNumber(name)) {
313  // trailing # with a number - like above, try to use the given number first
314  objname = name;
315  tryReuse = true;
316  startNumberingImmediately = false;
317  } else {
318  objname = name;
319  startNumberingImmediately = false;
320  }
321 
322  s = objname;
323  if (startNumberingImmediately) {
324  s += QLatin1Char('1');
325  }
326 
327  for (;;) {
328  const QList<QWidget *> list = qApp->topLevelWidgets();
329  bool found = false;
330  for (QWidget *w : list) {
331  if (w != q && w->objectName() == s) {
332  found = true;
333  break;
334  }
335  }
336  if (!found) {
337  break;
338  }
339  if (tryReuse) {
340  objname = name.left(name.length() - 1); // lose the hash
341  unusedNumber = 0; // start from 1 below
342  tryReuse = false;
343  }
344  s.setNum(++unusedNumber);
345  s = objname + s;
346  }
347  q->setObjectName(s);
348  q->winId(); // workaround for setWindowRole() crashing, and set also window role, just in case TT
349  q->setWindowRole(s); // will keep insisting that object name suddenly should not be used for window role
350 
351  dbusName = QLatin1Char('/') + QCoreApplication::applicationName() + QLatin1Char('/');
352  dbusName += q->objectName().replace(QLatin1Char('/'), QLatin1Char('_'));
353  // Clean up for dbus usage: any non-alphanumeric char should be turned into '_'
354  for (QChar &c : dbusName) {
355  if (!isValidDBusObjectPathCharacter(c)) {
356  c = QLatin1Char('_');
357  }
358  }
359 
360 #ifdef QT_DBUS_LIB
366 #endif
367 }
368 
369 void KMainWindowPrivate::setSettingsDirty(CallCompression callCompression)
370 {
371  if (!letDirtySettings) {
372  return;
373  }
374 
375  settingsDirty = true;
376  if (autoSaveSettings) {
377  if (callCompression == CompressCalls) {
378  if (!settingsTimer) {
379  settingsTimer = new QTimer(q);
380  settingsTimer->setInterval(500);
381  settingsTimer->setSingleShot(true);
382  QObject::connect(settingsTimer, &QTimer::timeout,
384  }
385  settingsTimer->start();
386  } else {
388  }
389  }
390 }
391 
392 void KMainWindowPrivate::setSizeDirty()
393 {
394  if (autoSaveWindowSize) {
395  if (!sizeTimer) {
396  sizeTimer = new QTimer(q);
397  sizeTimer->setInterval(500);
398  sizeTimer->setSingleShot(true);
399  QObject::connect(sizeTimer, SIGNAL(timeout()), q, SLOT(_k_slotSaveAutoSaveSize()));
400  }
401  sizeTimer->start();
402  }
403 }
404 
406 {
407  sMemberList()->removeAll(this);
408  delete static_cast<QObject *>(k_ptr->dockResizeListener); //so we don't get anymore events after k_ptr is destroyed
409  delete k_ptr;
410 }
411 
412 #if KXMLGUI_BUILD_DEPRECATED_SINCE(5, 0)
413 QMenu *KMainWindow::helpMenu(const QString &aboutAppText, bool showWhatsThis)
414 {
415  K_D(KMainWindow);
416  if (!d->helpMenu) {
417  if (aboutAppText.isEmpty()) {
418  d->helpMenu = new KHelpMenu(this, KAboutData::applicationData(), showWhatsThis);
419  } else {
420  d->helpMenu = new KHelpMenu(this, aboutAppText, showWhatsThis);
421  }
422 
423  if (!d->helpMenu) {
424  return nullptr;
425  }
426  }
427 
428  return d->helpMenu->menu();
429 }
430 
431 QMenu *KMainWindow::customHelpMenu(bool showWhatsThis)
432 {
433  K_D(KMainWindow);
434  if (!d->helpMenu) {
435  d->helpMenu = new KHelpMenu(this, QString(), showWhatsThis);
438  }
439 
440  return d->helpMenu->menu();
441 }
442 #endif
443 
445 {
447  if (!config) {
448  return false;
449  }
450 
451  KConfigGroup group(config, "Number");
452  const int n = group.readEntry("NumberOfWindows", 1);
453  return number >= 1 && number <= n;
454 }
455 
457 {
459  if (!config) {
460  return QString();
461  }
462 
463  KConfigGroup group(config, QByteArray(WINDOW_PROPERTIES).append(QByteArray::number(number)).constData());
464  if (!group.hasKey("ClassName")) {
465  return QString();
466  } else {
467  return group.readEntry("ClassName");
468  }
469 }
470 
471 bool KMainWindow::restore(int number, bool show)
472 {
473  if (!canBeRestored(number)) {
474  return false;
475  }
477  if (readPropertiesInternal(config, number)) {
478  if (show) {
480  }
481  return false;
482  }
483  return false;
484 }
485 
486 void KMainWindow::setCaption(const QString &caption)
487 {
488  setPlainCaption(caption);
489 }
490 
491 void KMainWindow::setCaption(const QString &caption, bool modified)
492 {
493  QString title = caption;
494  if (!title.contains(QLatin1String("[*]")) && !title.isEmpty()) { // append the placeholder so that the modified mechanism works
495  title.append(QLatin1String(" [*]"));
496  }
497  setPlainCaption(title);
498  setWindowModified(modified);
499 }
500 
502 {
503  setWindowTitle(caption);
504 }
505 
507 {
508  K_D(KMainWindow);
509  if (!d->helpMenu) {
510  d->helpMenu = new KHelpMenu(this);
511  if (!d->helpMenu) {
512  return;
513  }
514  }
515  d->helpMenu->appHelpActivated();
516 }
517 
519 {
520  K_D(KMainWindow);
521 
522  // Save settings if auto-save is enabled, and settings have changed
523  if (d->settingsTimer && d->settingsTimer->isActive()) {
524  d->settingsTimer->stop();
525  saveAutoSaveSettings();
526  }
527  if (d->sizeTimer && d->sizeTimer->isActive()) {
528  d->sizeTimer->stop();
529  d->_k_slotSaveAutoSaveSize();
530  }
531 
532  if (queryClose()) {
533  // widgets will start destroying themselves at this point and we don't
534  // want to save state anymore after this as it might be incorrect
535  d->autoSaveSettings = false;
536  d->letDirtySettings = false;
537  e->accept();
538  } else {
539  e->ignore(); //if the window should not be closed, don't close it
540  }
541 }
542 
544 {
545  return true;
546 }
547 
549 {
550 }
551 
553 {
554 }
555 
556 void KMainWindow::savePropertiesInternal(KConfig *config, int number)
557 {
558  K_D(KMainWindow);
559  const bool oldASWS = d->autoSaveWindowSize;
560  d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
561 
562  KConfigGroup cg(config, QByteArray(WINDOW_PROPERTIES).append(QByteArray::number(number)).constData());
563 
564  // store objectName, className, Width and Height for later restoring
565  // (Only useful for session management)
566  cg.writeEntry("ObjectName", objectName());
567  cg.writeEntry("ClassName", metaObject()->className());
568 
569  saveMainWindowSettings(cg); // Menubar, statusbar and Toolbar settings.
570 
571  cg = KConfigGroup(config, QByteArray::number(number).constData());
572  saveProperties(cg);
573 
574  d->autoSaveWindowSize = oldASWS;
575 }
576 
578 {
579  K_D(KMainWindow);
580  //qDebug(200) << "KMainWindow::saveMainWindowSettings " << cg.name();
581 
582  // Called by session management - or if we want to save the window size anyway
583  if (d->autoSaveWindowSize) {
585  }
586 
587  // One day will need to save the version number, but for now, assume 0
588  // Utilise the QMainWindow::saveState() functionality.
589  const QByteArray state = saveState();
590  cg.writeEntry("State", state.toBase64());
591 
592  QStatusBar *sb = internalStatusBar(this);
593  if (sb) {
594  if (!cg.hasDefault("StatusBar") && !sb->isHidden()) {
595  cg.revertToDefault("StatusBar");
596  } else {
597  cg.writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
598  }
599  }
600 
601  QMenuBar *mb = internalMenuBar(this);
602  if (mb) {
603  if (!cg.hasDefault("MenuBar") && !mb->isHidden()) {
604  cg.revertToDefault("MenuBar");
605  } else {
606  cg.writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
607  }
608  }
609 
610  if (!autoSaveSettings() || cg.name() == autoSaveGroup()) {
611  // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
612  if (!cg.hasDefault("ToolBarsMovable") && !KToolBar::toolBarsLocked()) {
613  cg.revertToDefault("ToolBarsMovable");
614  } else {
615  cg.writeEntry("ToolBarsMovable", KToolBar::toolBarsLocked() ? "Disabled" : "Enabled");
616  }
617  }
618 
619  int n = 1; // Toolbar counter. toolbars are counted from 1,
620  const auto toolBars = this->toolBars();
621  for (KToolBar *toolbar : toolBars) {
622  QByteArray groupName("Toolbar");
623  // Give a number to the toolbar, but prefer a name if there is one,
624  // because there's no real guarantee on the ordering of toolbars
625  groupName += (toolbar->objectName().isEmpty() ? QByteArray::number(n) : QByteArray(" ").append(toolbar->objectName().toUtf8()));
626 
627  KConfigGroup toolbarGroup(&cg, groupName.constData());
628  toolbar->saveSettings(toolbarGroup);
629  n++;
630  }
631 }
632 
633 bool KMainWindow::readPropertiesInternal(KConfig *config, int number)
634 {
635  K_D(KMainWindow);
636 
637  const bool oldLetDirtySettings = d->letDirtySettings;
638  d->letDirtySettings = false;
639 
640  if (number == 1) {
641  readGlobalProperties(config);
642  }
643 
644  // in order they are in toolbar list
645  KConfigGroup cg(config, QByteArray(WINDOW_PROPERTIES).append(QByteArray::number(number)).constData());
646 
647  // restore the object name (window role)
648  if (cg.hasKey("ObjectName")) {
649  setObjectName(cg.readEntry("ObjectName"));
650  }
651 
652  d->sizeApplied = false; // since we are changing config file, reload the size of the window
653  // if necessary. Do it before the call to applyMainWindowSettings.
654  applyMainWindowSettings(cg); // Menubar, statusbar and toolbar settings.
655 
656  KConfigGroup grp(config, QByteArray::number(number).constData());
657  readProperties(grp);
658 
659  d->letDirtySettings = oldLetDirtySettings;
660 
661  return true;
662 }
663 
665 {
666  K_D(KMainWindow);
667  //qDebug(200) << "KMainWindow::applyMainWindowSettings " << cg.name();
668 
669  QWidget *focusedWidget = QApplication::focusWidget();
670 
671  const bool oldLetDirtySettings = d->letDirtySettings;
672  d->letDirtySettings = false;
673 
674  if (!d->sizeApplied) {
675  winId(); // ensure there's a window created
677  // NOTICE: QWindow::setGeometry() does NOT impact the backing QWidget geometry even if the platform
678  // window was created -> QTBUG-40584. We therefore copy the size here.
679  // TODO: remove once this was resolved in QWidget QPA
680  resize(windowHandle()->size());
681  d->sizeApplied = true;
682  }
683 
684  QStatusBar *sb = internalStatusBar(this);
685  if (sb) {
686  QString entry = cg.readEntry("StatusBar", "Enabled");
687  sb->setVisible( entry != QLatin1String("Disabled") );
688  }
689 
690  QMenuBar *mb = internalMenuBar(this);
691  if (mb) {
692  QString entry = cg.readEntry("MenuBar", "Enabled");
693  mb->setVisible( entry != QLatin1String("Disabled") );
694  }
695 
696  if (!autoSaveSettings() || cg.name() == autoSaveGroup()) { // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
697  QString entry = cg.readEntry("ToolBarsMovable", "Disabled");
698  KToolBar::setToolBarsLocked(entry == QLatin1String("Disabled"));
699  }
700 
701  int n = 1; // Toolbar counter. toolbars are counted from 1,
702  const auto toolBars = this->toolBars();
703  for (KToolBar *toolbar : toolBars) {
704  QByteArray groupName("Toolbar");
705  // Give a number to the toolbar, but prefer a name if there is one,
706  // because there's no real guarantee on the ordering of toolbars
707  groupName += (toolbar->objectName().isEmpty() ? QByteArray::number(n) : QByteArray(" ").append(toolbar->objectName().toUtf8()));
708 
709  KConfigGroup toolbarGroup(&cg, groupName.constData());
710  toolbar->applySettings(toolbarGroup);
711  n++;
712  }
713 
714  QByteArray state;
715  if (cg.hasKey("State")) {
716  state = cg.readEntry("State", state);
717  state = QByteArray::fromBase64(state);
718  // One day will need to load the version number, but for now, assume 0
719  restoreState(state);
720  }
721 
722  if (focusedWidget) {
723  focusedWidget->setFocus();
724  }
725 
726  d->settingsDirty = false;
727  d->letDirtySettings = oldLetDirtySettings;
728 }
729 
730 #if KXMLGUI_BUILD_DEPRECATED_SINCE(5, 0)
732 {
734 }
735 #endif
736 
737 #if KXMLGUI_BUILD_DEPRECATED_SINCE(5, 0)
739 {
741 }
742 #endif
743 
745 {
746  K_D(KMainWindow);
747  d->setSettingsDirty();
748 }
749 
751 {
752  K_D(const KMainWindow);
753  return d->settingsDirty;
754 }
755 
756 void KMainWindow::setAutoSaveSettings(const QString &groupName, bool saveWindowSize)
757 {
758  setAutoSaveSettings(KConfigGroup(KSharedConfig::openConfig(), groupName), saveWindowSize);
759 }
760 
762  bool saveWindowSize)
763 {
764  K_D(KMainWindow);
765  d->autoSaveSettings = true;
766  d->autoSaveGroup = group;
767  d->autoSaveWindowSize = saveWindowSize;
768 
769  if (!saveWindowSize && d->sizeTimer) {
770  d->sizeTimer->stop();
771  }
772 
773  // Now read the previously saved settings
774  applyMainWindowSettings(d->autoSaveGroup);
775 }
776 
778 {
779  K_D(KMainWindow);
780  d->autoSaveSettings = false;
781  if (d->settingsTimer) {
782  d->settingsTimer->stop();
783  }
784 }
785 
787 {
788  K_D(const KMainWindow);
789  return d->autoSaveSettings;
790 }
791 
793 {
794  K_D(const KMainWindow);
795  return d->autoSaveSettings ? d->autoSaveGroup.name() : QString();
796 }
797 
799 {
800  K_D(const KMainWindow);
801  return d->autoSaveSettings ? d->autoSaveGroup : KConfigGroup();
802 }
803 
805 {
806  K_D(KMainWindow);
807  Q_ASSERT(d->autoSaveSettings);
808  //qDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings";
809  saveMainWindowSettings(d->autoSaveGroup);
810  d->autoSaveGroup.sync();
811  d->settingsDirty = false;
812 }
813 
815 {
816  K_D(KMainWindow);
817  switch (ev->type()) {
818 #if defined(Q_OS_WIN) || defined(Q_OS_OSX)
819  case QEvent::Move:
820 #endif
821  case QEvent::Resize:
822  d->setSizeDirty();
823  break;
824  case QEvent::Polish:
825  d->polish(this);
826  break;
827  case QEvent::ChildPolished: {
828  QChildEvent *event = static_cast<QChildEvent *>(ev);
829  QDockWidget *dock = qobject_cast<QDockWidget *>(event->child());
830  KToolBar *toolbar = qobject_cast<KToolBar *>(event->child());
831  QMenuBar *menubar = qobject_cast<QMenuBar *>(event->child());
832  if (dock) {
837 
838  // there is no signal emitted if the size of the dock changes,
839  // hence install an event filter instead
840  dock->installEventFilter(k_ptr->dockResizeListener);
841  } else if (toolbar) {
842  // there is no signal emitted if the size of the toolbar changes,
843  // hence install an event filter instead
844  toolbar->installEventFilter(k_ptr->dockResizeListener);
845  } else if (menubar) {
846  // there is no signal emitted if the size of the menubar changes,
847  // hence install an event filter instead
848  menubar->installEventFilter(k_ptr->dockResizeListener);
849  }
850  }
851  break;
852  case QEvent::ChildRemoved: {
853  QChildEvent *event = static_cast<QChildEvent *>(ev);
854  QDockWidget *dock = qobject_cast<QDockWidget *>(event->child());
855  KToolBar *toolbar = qobject_cast<KToolBar *>(event->child());
856  QMenuBar *menubar = qobject_cast<QMenuBar *>(event->child());
857  if (dock) {
862  dock->removeEventFilter(k_ptr->dockResizeListener);
863  } else if (toolbar) {
864  toolbar->removeEventFilter(k_ptr->dockResizeListener);
865  } else if (menubar) {
866  menubar->removeEventFilter(k_ptr->dockResizeListener);
867  }
868  }
869  break;
870  default:
871  break;
872  }
873  return QMainWindow::event(ev);
874 }
875 
877 {
878  return internalMenuBar(this);
879 }
880 
881 void KMainWindowPrivate::_k_slotSettingsChanged(int category)
882 {
883  Q_UNUSED(category);
884 
885  // This slot will be called when the style KCM changes settings that need
886  // to be set on the already running applications.
887 
888  // At this level (KMainWindow) the only thing we need to restore is the
889  // animations setting (whether the user wants builtin animations or not).
890 
891  q->setAnimated(q->style()->styleHint(QStyle::SH_Widget_Animate, nullptr, q));
892 }
893 
894 void KMainWindowPrivate::_k_slotSaveAutoSaveSize()
895 {
896  if (autoSaveGroup.isValid()) {
897  KWindowConfig::saveWindowSize(q->windowHandle(), autoSaveGroup);
898  }
899 }
900 
902 {
903  QString childName = name;
904  if (childName.isEmpty()) {
905  childName = QStringLiteral("mainToolBar");
906  }
907 
908  KToolBar *tb = findChild<KToolBar *>(childName);
909  if (tb) {
910  return tb;
911  }
912 
913  KToolBar *toolbar = new KToolBar(childName, this); // non-XMLGUI toolbar
914  return toolbar;
915 }
916 
918 {
919  QList<KToolBar *> ret;
920 
921  const auto theChildren = children();
922  for (QObject *child : theChildren)
923  if (KToolBar *toolBar = qobject_cast<KToolBar *>(child)) {
924  ret.append(toolBar);
925  }
926 
927  return ret;
928 }
929 
931 {
932  return *sMemberList();
933 }
934 
936 {
937  return k_func()->dbusName;
938 }
939 
940 #include "moc_kmainwindow.cpp"
941 #include "kmainwindow.moc"
bool event(QEvent *event) override
Reimplemented to catch QEvent::Polish in order to adjust the object name if needed, once all constructor code for the main window has run.
void resize(int w, int h)
FindDirectChildrenOnly
void setFallbackThemeName(const QString &name)
void appHelpActivated()
Open the help page for the application.
QString & append(QChar ch)
QEvent::Type type() const const
bool isHidden() const const
void setSettingsDirty()
Tell the main window that it should save its settings when being closed.
KMainWindow(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
Construct a main window.
QString writableLocation(QStandardPaths::StandardLocation type)
static void setToolBarsLocked(bool locked)
Allows you to lock and unlock all toolbars (i.e., disallow/allow moving of the toobars).
Definition: ktoolbar.cpp:1380
KCONFIGGUI_EXPORT void setSessionConfig(const QString &id, const QString &key)
void topLevelChanged(bool topLevel)
static KAboutData applicationData()
QWidget * window() const const
void showAboutApplication()
This signal is emitted from aboutApplication() if no "about application" string has been defined...
virtual void showAboutApplication()
This slot does nothing.
Definition: kmainwindow.h:612
void setWindowRole(const QString &role)
bool hasDefault(const QString &key) const
QStyle * style() const const
const QObjectList & children() const const
bool registerObject(const QString &path, QObject *object, QDBusConnection::RegisterOptions options)
virtual void setVisible(bool visible)
QList< KAboutPerson > translators() const
SH_Widget_Animate
virtual const QMetaObject * metaObject() const const
QString autoSaveGroup() const
void resetAutoSaveSettings()
Disable the auto-save-settings feature.
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
QDBusConnection sessionBus()
void saveWindowSize(KConfigGroup &config) const
For inherited classes.
bool exists() const const
static KGlobalSettings * self()
static const QString classNameOfToplevel(int number)
Returns the className() of the number of the toplevel window which should be restored.
QString i18ndc(const char *domain, const char *context, const char *text, const TYPE &arg...)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
void setWindowModified(bool)
KSharedConfigPtr config()
void restoreWindowSize(const KConfigGroup &config)
For inherited classes.
bool restore(int number, bool show=true)
Try to restore the toplevel widget as defined by number (1..X).
QSize size() const const
virtual void setPlainCaption(const QString &caption)
Make a plain caption without any modifications.
void timeout()
virtual void saveGlobalProperties(KConfig *sessionConfig)
Save your application-wide properties.
void setAnimated(bool enabled)
bool testAttribute(Qt::WidgetAttribute attribute) const const
void setFallbackSessionManagementEnabled(bool enabled)
void append(const T &value)
void saveAutoSaveSettings()
This slot should only be called in case you reimplement closeEvent() and if you are using the "auto-s...
Standard KDE help menu with dialog boxes.
Definition: khelpmenu.h:109
bool isAccepted() const const
void ignore()
QMenu * customHelpMenu(bool showWhatsThis=true)
Returns the help menu.
void installEventFilter(QObject *filterObj)
Top level main window.
Definition: kmainwindow.h:96
Q_OBJECTQ_OBJECT
void closeEvent(QCloseEvent *) override
Reimplemented to autosave settings and call queryClose().
void setFocus()
virtual bool event(QEvent *event) override
~KMainWindow() override
Destructor.
bool isEmpty() const const
QWidget * focusWidget()
virtual int styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const const =0
const char * constData() const const
QByteArray number(int n, int base)
bool sendEvent(QObject *receiver, QEvent *event)
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
virtual bool eventFilter(QObject *watched, QEvent *event)
bool autoSaveSettings() const
static bool canBeRestored(int number)
If the session did contain so high a number, true is returned, else false.
WId winId() const const
bool hasMenuBar()
Returns true, if there is a menubar.
virtual bool queryClose()
Called before the window is closed, either by the user or indirectly by the session manager...
bool allowsInteraction()
QMenu * helpMenu(const QString &aboutAppText=QString(), bool showWhatsThis=true)
Retrieve the standard help menu.
virtual void setCaption(const QString &caption)
Makes a KDE compliant caption (window title).
QString sessionId() const const
ushort unicode() const const
void commitDataRequest(QSessionManager &manager)
QByteArray & append(char ch)
KGuiItem discard()
QString fallbackThemeName()
void accept()
static void setApplicationData(const KAboutData &aboutData)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString sessionKey() const const
QString name() const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
bool hasKey(const QString &key) const
QWindow * windowHandle() const const
WA_WState_Hidden
void setAutoSaveSettings(const QString &groupName=QStringLiteral("MainWindow"), bool saveWindowSize=true)
Call this to enable "auto-save" of toolbar/menubar/statusbar settings (and optionally window size)...
virtual void setVisible(bool visible) override
void dockLocationChanged(Qt::DockWidgetArea area)
QByteArray fromBase64(const QByteArray &base64, QByteArray::Base64Options options)
void saveStateRequest(QSessionManager &manager)
Floatable toolbar with auto resize.
Definition: ktoolbar.h:59
QString & setNum(short n, int base)
void setWindowTitle(const QString &)
KToolBar * toolBar(const QString &name=QString())
Returns a pointer to the toolbar with the specified name.
bool settingsDirty() const
For inherited classes.
QString dbusName() const
Returns the path under which this window&#39;s D-Bus object is exported.
KCONFIGGUI_EXPORT void restoreWindowSize(QWindow *window, const KConfigGroup &config)
int length() const const
KCONFIGGUI_EXPORT KConfig * sessionConfig()
QString left(int n) const const
void show()
void setDiscardCommand(const QStringList &command)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T qobject_cast(QObject *object)
QObject * parent() const const
virtual bool event(QEvent *event) override
T readEntry(const QString &key, const T &aDefault) const
typedef WindowFlags
virtual void readGlobalProperties(KConfig *sessionConfig)
The counterpart of saveGlobalProperties().
void revertToDefault(const QString &key)
KCONFIGGUI_EXPORT void saveWindowSize(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options=KConfigGroup::Normal)
void saveMainWindowSettings(KConfigGroup &config)
Save settings for statusbar, menubar and toolbar to their respective groups in the config group confi...
void removeEventFilter(QObject *obj)
QByteArray toBase64(QByteArray::Base64Options options) const const
static QList< KMainWindow * > memberList()
List of members of KMainWindow class.
static bool toolBarsLocked()
Returns whether the toolbars are locked (i.e., moving of the toobars disallowed). ...
Definition: ktoolbar.cpp:1395
KConfigGroup autoSaveConfigGroup() const
QString applicationName()
virtual void applyMainWindowSettings(const KConfigGroup &config)
Read settings for statusbar, menubar and toolbar from their respective groups in the config file and ...
QList< KToolBar * > toolBars() const
KAboutData & setTranslator(const QString &name, const QString &emailAddress)
T findChild(const QString &name, Qt::FindChildOptions options) const const
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.