• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • widgets
kmainwindow.cpp
Go to the documentation of this file.
1  /* This file is part of the KDE libraries
2  Copyright
3  (C) 2000 Reginald Stadlbauer (reggie@kde.org)
4  (C) 1997 Stephan Kulow (coolo@kde.org)
5  (C) 1997-2000 Sven Radej (radej@kde.org)
6  (C) 1997-2000 Matthias Ettrich (ettrich@kde.org)
7  (C) 1999 Chris Schlaeger (cs@kde.org)
8  (C) 2002 Joseph Wenninger (jowenn@kde.org)
9  (C) 2005-2006 Hamish Rodda (rodda@kde.org)
10  (C) 2000-2008 David Faure (faure@kde.org)
11 
12  This library is free software; you can redistribute it and/or
13  modify it under the terms of the GNU Library General Public
14  License version 2 as published by the Free Software Foundation.
15 
16  This library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  Library General Public License for more details.
20 
21  You should have received a copy of the GNU Library General Public License
22  along with this library; see the file COPYING.LIB. If not, write to
23  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  Boston, MA 02110-1301, USA.
25  */
26 
27 #include "kmainwindow.h"
28 #include "kmainwindow_p.h"
29 #include "kmainwindowiface_p.h"
30 #include "ktoolbarhandler_p.h"
31 #include "kcmdlineargs.h"
32 #include "ktoggleaction.h"
33 #include "ksessionmanager.h"
34 #include "kstandardaction.h"
35 
36 #include <QtCore/QList>
37 #include <QtCore/QObject>
38 #include <QtCore/QTimer>
39 #include <QtGui/QCloseEvent>
40 #include <QtGui/QDesktopWidget>
41 #include <QtGui/QDockWidget>
42 #include <QtGui/QLayout>
43 #include <QtGui/QSessionManager>
44 #include <QtGui/QStyle>
45 #include <QtGui/QWidget>
46 
47 #include <kaction.h>
48 #include <kapplication.h>
49 #include <kauthorized.h>
50 #include <kconfig.h>
51 #include <kdebug.h>
52 #include <kdialog.h>
53 #include <khelpmenu.h>
54 #include <klocale.h>
55 #include <kmenubar.h>
56 #include <kstandarddirs.h>
57 #include <kstatusbar.h>
58 #include <ktoolbar.h>
59 #include <kwindowsystem.h>
60 #include <kconfiggroup.h>
61 #include <kglobalsettings.h>
62 
63 #if defined Q_WS_X11
64 #include <qx11info_x11.h>
65 #include <netwm.h>
66 #endif
67 
68 #include <stdlib.h>
69 #include <ctype.h>
70 #include <assert.h>
71 
72 #include <config.h>
73 
74 static bool no_query_exit = false;
75 
76 static KMenuBar *internalMenuBar(KMainWindow *mw)
77 {
78  return KGlobal::findDirectChild<KMenuBar *>(mw);
79 }
80 
81 static KStatusBar *internalStatusBar(KMainWindow *mw)
82 {
83  // Don't use qFindChild here, it's recursive!
84  // (== slow, but also finds konqueror's per-view statusbars)
85  return KGlobal::findDirectChild<KStatusBar *>(mw);
86 }
87 
95 class DockResizeListener : public QObject
96 {
97 public:
98  DockResizeListener(KMainWindow *win);
99  virtual ~DockResizeListener();
100  virtual bool eventFilter(QObject *watched, QEvent *event);
101 
102 private:
103  KMainWindow *m_win;
104 };
105 
106 DockResizeListener::DockResizeListener(KMainWindow *win) :
107  QObject(win),
108  m_win(win)
109 {
110 }
111 
112 DockResizeListener::~DockResizeListener()
113 {
114 }
115 
116 bool DockResizeListener::eventFilter(QObject *watched, QEvent *event)
117 {
118  switch( event->type() ) {
119  case QEvent::Resize:
120  case QEvent::Move:
121  case QEvent::Hide:
122  m_win->k_ptr->setSettingsDirty(KMainWindowPrivate::CompressCalls);
123  break;
124 
125  default:
126  break;
127  }
128 
129  return QObject::eventFilter(watched, event);
130 }
131 
132 class KMWSessionManager : public KSessionManager
133 {
134 public:
135  KMWSessionManager()
136  {
137  }
138  ~KMWSessionManager()
139  {
140  }
141  bool dummyInit() { return true; }
142  bool saveState( QSessionManager& )
143  {
144  KConfig* config = KApplication::kApplication()->sessionConfig();
145  if ( KMainWindow::memberList().count() ){
146  // According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this
147  // hook is useful for better document orientation
148  KMainWindow::memberList().first()->saveGlobalProperties(config);
149  }
150 
151  int n = 0;
152  foreach (KMainWindow* mw, KMainWindow::memberList()) {
153  n++;
154  mw->savePropertiesInternal(config, n);
155  }
156 
157  KConfigGroup group( config, "Number" );
158  group.writeEntry("NumberOfWindows", n );
159  return true;
160  }
161 
162  bool commitData( QSessionManager& sm )
163  {
164  // not really a fast method but the only compatible one
165  if ( sm.allowsInteraction() ) {
166  bool canceled = false;
167  ::no_query_exit = true;
168 
169  foreach (KMainWindow *window, KMainWindow::memberList()) {
170  if ( !window->testAttribute( Qt::WA_WState_Hidden ) ) {
171  QCloseEvent e;
172  QApplication::sendEvent( window, &e );
173  canceled = !e.isAccepted();
174  if (canceled)
175  break;
176  /* Don't even think_about deleting widgets with
177  Qt::WDestructiveClose flag set at this point. We
178  are faking a close event, but we are *not*_
179  closing the window. The purpose of the faked
180  close event is to prepare the application so it
181  can safely be quit without the user losing data
182  (possibly showing a message box "do you want to
183  save this or that?"). It is possible that the
184  session manager quits the application later
185  (emitting QApplication::aboutToQuit() when this
186  happens), but it is also possible that the user
187  cancels the shutdown, so the application will
188  continue to run.
189  */
190  }
191  }
192  ::no_query_exit = false;
193  if (canceled)
194  return false;
195 
196  KMainWindow* last = 0;
197  foreach (KMainWindow *window, KMainWindow::memberList()) {
198  if ( !window->testAttribute( Qt::WA_WState_Hidden ) ) {
199  last = window;
200  }
201  }
202  if ( last )
203  return last->queryExit();
204  // else
205  return true;
206  }
207 
208  // the user wants it, the user gets it
209  return true;
210  }
211 };
212 
213 K_GLOBAL_STATIC(KMWSessionManager, ksm)
214 K_GLOBAL_STATIC(QList<KMainWindow*>, sMemberList)
215 static bool being_first = true;
216 
217 KMainWindow::KMainWindow( QWidget* parent, Qt::WindowFlags f )
218  : QMainWindow(parent, f), k_ptr(new KMainWindowPrivate)
219 {
220  k_ptr->init(this);
221 }
222 
223 KMainWindow::KMainWindow(KMainWindowPrivate &dd, QWidget *parent, Qt::WindowFlags f)
224  : QMainWindow(parent, f), k_ptr(&dd)
225 {
226  k_ptr->init(this);
227 }
228 
229 void KMainWindowPrivate::init(KMainWindow *_q)
230 {
231  KGlobal::ref();
232 
233  // We set allow quit to true when the first mainwindow is created, so that when the refcounting
234  // reaches 0 the application can quit. We don't want this to happen before the first mainwindow
235  // is created, otherwise running a job in main would exit the app too early.
236  KGlobal::setAllowQuit(true);
237 
238  q = _q;
239 
240  q->setAnimated(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects);
241 
242  q->setAttribute( Qt::WA_DeleteOnClose );
243 
244  // We handle this functionality (quitting the app) ourselves, with KGlobal::ref/deref.
245  // This makes apps stay alive even if they only have a systray icon visible, or
246  // a progress widget with "keep open" checked, for instance.
247  // So don't let the default Qt mechanism allow any toplevel widget to just quit the app on us.
248  // Setting WA_QuitOnClose to false for all KMainWindows is not enough, any progress widget
249  // or dialog box would still quit the app...
250  if (qApp)
251  qApp->setQuitOnLastWindowClosed(false);
252 
253  helpMenu = 0;
254 
255  //actionCollection()->setWidget( this );
256  QObject::connect(qApp, SIGNAL(aboutToQuit()), q, SLOT(_k_shuttingDown()));
257  QObject::connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)),
258  q, SLOT(_k_slotSettingsChanged(int)));
259 
260  // force KMWSessionManager creation - someone a better idea?
261  ksm->dummyInit();
262 
263  sMemberList->append( q );
264 
265  settingsDirty = false;
266  autoSaveSettings = false;
267  autoSaveWindowSize = true; // for compatibility
268  //d->kaccel = actionCollection()->kaccel();
269  settingsTimer = 0;
270  sizeTimer = 0;
271  shuttingDown = false;
272  if ((care_about_geometry = being_first)) {
273  being_first = false;
274 
275  QString geometry;
276  KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
277  if (args && args->isSet("geometry"))
278  geometry = args->getOption("geometry");
279 
280  if ( geometry.isNull() ) // if there is no geometry, it doesn't matter
281  care_about_geometry = false;
282  else
283  q->parseGeometry(false);
284  }
285 
286  q->setWindowTitle( KGlobal::caption() );
287 
288  dockResizeListener = new DockResizeListener(_q);
289  letDirtySettings = true;
290 
291  sizeApplied = false;
292 }
293 
294 static bool endsWithHashNumber( const QString& s )
295 {
296  for( int i = s.length() - 1;
297  i > 0;
298  --i )
299  {
300  if( s[ i ] == '#' && i != s.length() - 1 )
301  return true; // ok
302  if( !s[ i ].isDigit())
303  break;
304  }
305  return false;
306 }
307 
308 static inline bool isValidDBusObjectPathCharacter(const QChar &c)
309 {
310  register ushort u = c.unicode();
311  return (u >= 'a' && u <= 'z')
312  || (u >= 'A' && u <= 'Z')
313  || (u >= '0' && u <= '9')
314  || (u == '_') || (u == '/');
315 }
316 
317 void KMainWindowPrivate::polish(KMainWindow *q)
318 {
319  // Set a unique object name. Required by session management, window management, and for the dbus interface.
320  QString objname;
321  QString s;
322  int unusedNumber = 1;
323  const QString name = q->objectName();
324  bool startNumberingImmediately = true;
325  bool tryReuse = false;
326  if ( name.isEmpty() )
327  { // no name given
328  objname = "MainWindow#";
329  }
330  else if( name.endsWith( QLatin1Char( '#' ) ) )
331  { // trailing # - always add a number - KWin uses this for better grouping
332  objname = name;
333  }
334  else if( endsWithHashNumber( name ))
335  { // trailing # with a number - like above, try to use the given number first
336  objname = name;
337  tryReuse = true;
338  startNumberingImmediately = false;
339  }
340  else
341  {
342  objname = name;
343  startNumberingImmediately = false;
344  }
345 
346  s = objname;
347  if ( startNumberingImmediately )
348  s += '1';
349 
350  for(;;) {
351  const QList<QWidget*> list = qApp->topLevelWidgets();
352  bool found = false;
353  foreach ( QWidget* w, list ) {
354  if( w != q && w->objectName() == s )
355  {
356  found = true;
357  break;
358  }
359  }
360  if( !found )
361  break;
362  if( tryReuse ) {
363  objname = name.left( name.length() - 1 ); // lose the hash
364  unusedNumber = 0; // start from 1 below
365  tryReuse = false;
366  }
367  s.setNum( ++unusedNumber );
368  s = objname + s;
369  }
370  q->setObjectName( s );
371  q->winId(); // workaround for setWindowRole() crashing, and set also window role, just in case TT
372  q->setWindowRole( s ); // will keep insisting that object name suddenly should not be used for window role
373 
374  dbusName = '/' + qApp->applicationName() + '/' + q->objectName().replace(QLatin1Char('/'), QLatin1Char('_'));
375  // Clean up for dbus usage: any non-alphanumeric char should be turned into '_'
376  const int len = dbusName.length();
377  for ( int i = 0; i < len; ++i ) {
378  if ( !isValidDBusObjectPathCharacter( dbusName[i] ) )
379  dbusName[i] = QLatin1Char('_');
380  }
381 
382  QDBusConnection::sessionBus().registerObject(dbusName, q, QDBusConnection::ExportScriptableSlots |
383  QDBusConnection::ExportScriptableProperties |
384  QDBusConnection::ExportNonScriptableSlots |
385  QDBusConnection::ExportNonScriptableProperties |
386  QDBusConnection::ExportAdaptors);
387 }
388 
389 void KMainWindowPrivate::setSettingsDirty(CallCompression callCompression)
390 {
391  if (!letDirtySettings) {
392  return;
393  }
394 
395  settingsDirty = true;
396  if (autoSaveSettings) {
397  if (callCompression == CompressCalls) {
398  if (!settingsTimer) {
399  settingsTimer = new QTimer(q);
400  settingsTimer->setInterval(500);
401  settingsTimer->setSingleShot(true);
402  QObject::connect(settingsTimer, SIGNAL(timeout()), q, SLOT(saveAutoSaveSettings()));
403  }
404  settingsTimer->start();
405  } else {
406  q->saveAutoSaveSettings();
407  }
408  }
409 }
410 
411 void KMainWindowPrivate::setSizeDirty()
412 {
413  if (autoSaveWindowSize) {
414  if (!sizeTimer) {
415  sizeTimer = new QTimer(q);
416  sizeTimer->setInterval(500);
417  sizeTimer->setSingleShot(true);
418  QObject::connect(sizeTimer, SIGNAL(timeout()), q, SLOT(_k_slotSaveAutoSaveSize()));
419  }
420  sizeTimer->start();
421  }
422 }
423 
424 void KMainWindow::parseGeometry(bool parsewidth)
425 {
426  K_D(KMainWindow);
427  QString cmdlineGeometry;
428  KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
429  if (args->isSet("geometry"))
430  cmdlineGeometry = args->getOption("geometry");
431 
432  assert ( !cmdlineGeometry.isNull() );
433  assert ( d->care_about_geometry );
434  Q_UNUSED(d); // fix compiler warning in release mode
435 
436 #if defined Q_WS_X11
437  int x, y;
438  int w, h;
439  int m = XParseGeometry( cmdlineGeometry.toLatin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h);
440  if (parsewidth) {
441  const QSize minSize = minimumSize();
442  const QSize maxSize = maximumSize();
443  if ( !(m & WidthValue) )
444  w = width();
445  if ( !(m & HeightValue) )
446  h = height();
447  w = qMin(w,maxSize.width());
448  h = qMin(h,maxSize.height());
449  w = qMax(w,minSize.width());
450  h = qMax(h,minSize.height());
451  resize(w, h);
452  } else {
453  if ( (m & XNegative) )
454  x = KApplication::desktop()->width() + x - w;
455  else if ( !(m & XValue) )
456  x = geometry().x();
457  if ( (m & YNegative) )
458  y = KApplication::desktop()->height() + y - h;
459  else if ( !(m & YValue) )
460  y = geometry().y();
461 
462  move(x, y);
463  }
464 #endif
465 }
466 
467 KMainWindow::~KMainWindow()
468 {
469  sMemberList->removeAll( this );
470  delete static_cast<QObject *>(k_ptr->dockResizeListener); //so we don't get anymore events after k_ptr is destroyed
471  delete k_ptr;
472  KGlobal::deref();
473 }
474 
475 KMenu* KMainWindow::helpMenu( const QString &aboutAppText, bool showWhatsThis )
476 {
477  K_D(KMainWindow);
478  if(!d->helpMenu) {
479  if ( aboutAppText.isEmpty() )
480  d->helpMenu = new KHelpMenu( this, KGlobal::mainComponent().aboutData(), showWhatsThis);
481  else
482  d->helpMenu = new KHelpMenu( this, aboutAppText, showWhatsThis );
483 
484  if (!d->helpMenu)
485  return 0;
486  }
487 
488  return d->helpMenu->menu();
489 }
490 
491 KMenu* KMainWindow::customHelpMenu( bool showWhatsThis )
492 {
493  K_D(KMainWindow);
494  if (!d->helpMenu) {
495  d->helpMenu = new KHelpMenu( this, QString(), showWhatsThis );
496  connect(d->helpMenu, SIGNAL(showAboutApplication()),
497  this, SLOT(showAboutApplication()));
498  }
499 
500  return d->helpMenu->menu();
501 }
502 
503 bool KMainWindow::canBeRestored( int number )
504 {
505  if ( !qApp->isSessionRestored() )
506  return false;
507  KConfig *config = kapp->sessionConfig();
508  if ( !config )
509  return false;
510 
511  KConfigGroup group( config, "Number" );
512  const int n = group.readEntry( "NumberOfWindows", 1 );
513  return number >= 1 && number <= n;
514 }
515 
516 const QString KMainWindow::classNameOfToplevel( int number )
517 {
518  if ( !qApp->isSessionRestored() )
519  return QString();
520  KConfig *config = kapp->sessionConfig();
521  if ( !config )
522  return QString();
523  QString s;
524  s.setNum( number );
525  s.prepend( QLatin1String("WindowProperties") );
526 
527  KConfigGroup group( config, s );
528  if ( !group.hasKey( "ClassName" ) )
529  return QString();
530  else
531  return group.readEntry( "ClassName" );
532 }
533 
534 bool KMainWindow::restore( int number, bool show )
535 {
536  if ( !canBeRestored( number ) )
537  return false;
538  KConfig *config = kapp->sessionConfig();
539  if ( readPropertiesInternal( config, number ) ){
540  if ( show )
541  KMainWindow::show();
542  return false;
543  }
544  return false;
545 }
546 
547 void KMainWindow::setCaption( const QString &caption )
548 {
549  setPlainCaption( KDialog::makeStandardCaption( caption, this ) );
550 }
551 
552 void KMainWindow::setCaption( const QString &caption, bool modified )
553 {
554  KDialog::CaptionFlags flags = KDialog::HIGCompliantCaption;
555 
556  if ( modified )
557  {
558  flags |= KDialog::ModifiedCaption;
559  }
560 
561  setPlainCaption( KDialog::makeStandardCaption(caption, this, flags) );
562 }
563 
564 void KMainWindow::setPlainCaption( const QString &caption )
565 {
566  setWindowTitle(caption);
567 }
568 
569 void KMainWindow::appHelpActivated( void )
570 {
571  K_D(KMainWindow);
572  if( !d->helpMenu ) {
573  d->helpMenu = new KHelpMenu( this );
574  if ( !d->helpMenu )
575  return;
576  }
577  d->helpMenu->appHelpActivated();
578 }
579 
580 void KMainWindow::closeEvent ( QCloseEvent *e )
581 {
582  K_D(KMainWindow);
583 
584  // Save settings if auto-save is enabled, and settings have changed
585  if (d->settingsTimer && d->settingsTimer->isActive()) {
586  d->settingsTimer->stop();
587  saveAutoSaveSettings();
588  }
589  if (d->sizeTimer && d->sizeTimer->isActive()) {
590  d->sizeTimer->stop();
591  d->_k_slotSaveAutoSaveSize();
592  }
593 
594  if (queryClose()) {
595  e->accept();
596 
597  int not_withdrawn = 0;
598  foreach (KMainWindow* mw, KMainWindow::memberList()) {
599  if ( !mw->isHidden() && mw->isTopLevel() && mw != this )
600  not_withdrawn++;
601  }
602 
603  if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted?
604  if (!( queryExit() && ( !kapp || !kapp->sessionSaving() ) && !d->shuttingDown )) {
605  // cancel closing, it's stupid to end up with no windows at all....
606  e->ignore();
607  }
608  }
609  } else e->ignore(); //if the window should not be closed, don't close it
610 }
611 
612 bool KMainWindow::queryExit()
613 {
614  return true;
615 }
616 
617 bool KMainWindow::queryClose()
618 {
619  return true;
620 }
621 
622 void KMainWindow::saveGlobalProperties( KConfig* )
623 {
624 }
625 
626 void KMainWindow::readGlobalProperties( KConfig* )
627 {
628 }
629 
630 void KMainWindow::showAboutApplication()
631 {
632 }
633 
634 void KMainWindow::savePropertiesInternal( KConfig *config, int number )
635 {
636  K_D(KMainWindow);
637  const bool oldASWS = d->autoSaveWindowSize;
638  d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
639 
640  QString s;
641  s.setNum(number);
642  s.prepend(QLatin1String("WindowProperties"));
643  KConfigGroup cg(config, s);
644 
645  // store objectName, className, Width and Height for later restoring
646  // (Only useful for session management)
647  cg.writeEntry(QLatin1String("ObjectName"), objectName());
648  cg.writeEntry(QLatin1String("ClassName"), metaObject()->className());
649 
650  saveMainWindowSettings(cg); // Menubar, statusbar and Toolbar settings.
651 
652  s.setNum(number);
653  cg = KConfigGroup(config, s);
654  saveProperties(cg);
655 
656  d->autoSaveWindowSize = oldASWS;
657 }
658 
659 void KMainWindow::saveMainWindowSettings(const KConfigGroup &_cg)
660 {
661  K_D(KMainWindow);
662  //kDebug(200) << "KMainWindow::saveMainWindowSettings " << _cg.name();
663 
664  // Called by session management - or if we want to save the window size anyway
665  if ( d->autoSaveWindowSize )
666  saveWindowSize( _cg );
667 
668  KConfigGroup cg(_cg); // for saving
669 
670  // One day will need to save the version number, but for now, assume 0
671  // Utilise the QMainWindow::saveState() functionality.
672  const QByteArray state = saveState();
673  cg.writeEntry(QString("State"), state.toBase64());
674 
675  QStatusBar* sb = internalStatusBar(this);
676  if (sb) {
677  if(!cg.hasDefault("StatusBar") && !sb->isHidden() )
678  cg.revertToDefault("StatusBar");
679  else
680  cg.writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
681  }
682 
683  QMenuBar* mb = internalMenuBar(this);
684  if (mb) {
685  const QString MenuBar = QLatin1String("MenuBar");
686  if(!cg.hasDefault("MenuBar") && !mb->isHidden() )
687  cg.revertToDefault("MenuBar");
688  else
689  cg.writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
690  }
691 
692  if ( !autoSaveSettings() || cg.name() == autoSaveGroup() ) { // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
693  if(!cg.hasDefault("ToolBarsMovable") && !KToolBar::toolBarsLocked())
694  cg.revertToDefault("ToolBarsMovable");
695  else
696  cg.writeEntry("ToolBarsMovable", KToolBar::toolBarsLocked() ? "Disabled" : "Enabled");
697  }
698 
699  int n = 1; // Toolbar counter. toolbars are counted from 1,
700  foreach (KToolBar* toolbar, toolBars()) {
701  QString group("Toolbar");
702  // Give a number to the toolbar, but prefer a name if there is one,
703  // because there's no real guarantee on the ordering of toolbars
704  group += (toolbar->objectName().isEmpty() ? QString::number(n) : QString(" ")+toolbar->objectName());
705 
706  KConfigGroup toolbarGroup(&cg, group);
707  toolbar->saveSettings(toolbarGroup);
708  n++;
709  }
710 }
711 
712 bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
713 {
714  K_D(KMainWindow);
715 
716  const bool oldLetDirtySettings = d->letDirtySettings;
717  d->letDirtySettings = false;
718 
719  if ( number == 1 )
720  readGlobalProperties( config );
721 
722  // in order they are in toolbar list
723  QString s;
724  s.setNum(number);
725  s.prepend(QLatin1String("WindowProperties"));
726 
727  KConfigGroup cg(config, s);
728 
729  // restore the object name (window role)
730  if ( cg.hasKey(QLatin1String("ObjectName" )) )
731  setObjectName( cg.readEntry("ObjectName").toLatin1()); // latin1 is right here
732 
733  d->sizeApplied = false; // since we are changing config file, reload the size of the window
734  // if necessary. Do it before the call to applyMainWindowSettings.
735  applyMainWindowSettings(cg); // Menubar, statusbar and toolbar settings.
736 
737  s.setNum(number);
738  KConfigGroup grp(config, s);
739  readProperties(grp);
740 
741  d->letDirtySettings = oldLetDirtySettings;
742 
743  return true;
744 }
745 
746 void KMainWindow::applyMainWindowSettings(const KConfigGroup &cg, bool force)
747 {
748  K_D(KMainWindow);
749  kDebug(200) << "KMainWindow::applyMainWindowSettings " << cg.name();
750 
751  QWidget *focusedWidget = QApplication::focusWidget();
752 
753  const bool oldLetDirtySettings = d->letDirtySettings;
754  d->letDirtySettings = false;
755 
756  if (!d->sizeApplied) {
757  restoreWindowSize(cg);
758  d->sizeApplied = true;
759  }
760 
761  QStatusBar* sb = internalStatusBar(this);
762  if (sb) {
763  QString entry = cg.readEntry("StatusBar", "Enabled");
764  if ( entry == "Disabled" )
765  sb->hide();
766  else
767  sb->show();
768  }
769 
770  QMenuBar* mb = internalMenuBar(this);
771  if (mb) {
772  QString entry = cg.readEntry ("MenuBar", "Enabled");
773  if ( entry == "Disabled" )
774  mb->hide();
775  else
776  mb->show();
777  }
778 
779  if ( !autoSaveSettings() || cg.name() == autoSaveGroup() ) { // TODO should be cg == d->autoSaveGroup, to compare both kconfig and group name
780  QString entry = cg.readEntry ("ToolBarsMovable", "Disabled");
781  if ( entry == "Disabled" )
782  KToolBar::setToolBarsLocked(true);
783  else
784  KToolBar::setToolBarsLocked(false);
785  }
786 
787  int n = 1; // Toolbar counter. toolbars are counted from 1,
788  foreach (KToolBar* toolbar, toolBars()) {
789  QString group("Toolbar");
790  // Give a number to the toolbar, but prefer a name if there is one,
791  // because there's no real guarantee on the ordering of toolbars
792  group += (toolbar->objectName().isEmpty() ? QString::number(n) : QString(" ")+toolbar->objectName());
793 
794  KConfigGroup toolbarGroup(&cg, group);
795  toolbar->applySettings(toolbarGroup, force);
796  n++;
797  }
798 
799  QByteArray state;
800  if (cg.hasKey("State")) {
801  state = cg.readEntry("State", state);
802  state = QByteArray::fromBase64(state);
803  // One day will need to load the version number, but for now, assume 0
804  restoreState(state);
805  }
806 
807  if (focusedWidget) {
808  focusedWidget->setFocus();
809  }
810 
811  d->settingsDirty = false;
812  d->letDirtySettings = oldLetDirtySettings;
813 }
814 
815 #ifdef Q_WS_WIN
816 
817 /*
818  The win32 implementation for restoring/savin windows size differs
819  from the unix/max implementation in three topics:
820 
821 1. storing and restoring the position, which may not work on x11
822  see http://doc.trolltech.com/4.3/geometry.html#x11-peculiarities
823 2. using QWidget::saveGeometry() and QWidget::restoreGeometry()
824  this would probably be usable on x11 and/or on mac, but I'm unable to
825  check this on unix/mac, so I leave this fix to the x11/mac experts.
826 3. store geometry separately for each resolution -> on unix/max the size
827  and with of the window are already saved separately on non windows
828  system although not using ...Geometry functions -> could also be
829  fixed by x11/mac experts.
830 */
831 void KMainWindow::restoreWindowSize( const KConfigGroup & _cg )
832 {
833  K_D(KMainWindow);
834 
835  int scnum = QApplication::desktop()->screenNumber(window());
836  QRect desk = QApplication::desktop()->screenGeometry(scnum);
837 
838  QString geometryKey = QString::fromLatin1("geometry-%1-%2").arg(desk.width()).arg(desk.height());
839  QByteArray geometry = _cg.readEntry( geometryKey, QByteArray() );
840  // if first time run, center window
841  if (!restoreGeometry( QByteArray::fromBase64(geometry) ))
842  move( (desk.width()-width())/2, (desk.height()-height())/2 );
843 }
844 
845 void KMainWindow::saveWindowSize( const KConfigGroup & _cg ) const
846 {
847  K_D(const KMainWindow);
848  int scnum = QApplication::desktop()->screenNumber(window());
849  QRect desk = QApplication::desktop()->screenGeometry(scnum);
850 
851  // geometry is saved separately for each resolution
852  QString geometryKey = QString::fromLatin1("geometry-%1-%2").arg(desk.width()).arg(desk.height());
853  QByteArray geometry = saveGeometry();
854  KConfigGroup cg(_cg);
855  cg.writeEntry( geometryKey, geometry.toBase64() );
856 }
857 #else
858 void KMainWindow::saveWindowSize( const KConfigGroup & _cg ) const
859 {
860  K_D(const KMainWindow);
861  int scnum = QApplication::desktop()->screenNumber(window());
862  QRect desk = QApplication::desktop()->screenGeometry(scnum);
863 
864  int w, h;
865 #if defined Q_WS_X11
866  // save maximalization as desktop size + 1 in that direction
867  KWindowInfo info = KWindowSystem::windowInfo( winId(), NET::WMState );
868  w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
869  h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
870 #else
871  if (isMaximized()) {
872  w = desk.width() + 1;
873  h = desk.height() + 1;
874  } else {
875  w = width();
876  h = height();
877  }
878  //TODO: add "Maximized" property instead "+1" hack
879 #endif
880  KConfigGroup cg(_cg);
881 
882  QRect size( desk.width(), w, desk.height(), h );
883  bool defaultSize = (size == d->defaultWindowSize);
884  QString widthString = QString::fromLatin1("Width %1").arg(desk.width());
885  QString heightString = QString::fromLatin1("Height %1").arg(desk.height());
886  if (!cg.hasDefault(widthString) && defaultSize)
887  cg.revertToDefault(widthString);
888  else
889  cg.writeEntry(widthString, w );
890 
891  if (!cg.hasDefault(heightString) && defaultSize)
892  cg.revertToDefault(heightString);
893  else
894  cg.writeEntry(heightString, h );
895 }
896 
897 void KMainWindow::restoreWindowSize( const KConfigGroup & config )
898 {
899  K_D(KMainWindow);
900  if (d->care_about_geometry) {
901  parseGeometry(true);
902  } else {
903  // restore the size
904  const int scnum = QApplication::desktop()->screenNumber(window());
905  QRect desk = QApplication::desktop()->screenGeometry(scnum);
906 
907  if ( d->defaultWindowSize.isNull() ) // only once
908  d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values
909  const QSize size( config.readEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ),
910  config.readEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) );
911  if ( !size.isEmpty() ) {
912 #ifdef Q_WS_X11
913  int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
914  | ( size.height() > desk.height() ? NET::MaxVert : 0 );
915  if(( state & NET::Max ) == NET::Max )
916  resize( desk.width(), desk.height() ); // WORKAROUND: this should not be needed. KWindowSystem::setState
917  // should be enough for maximizing. (ereslibre)
918  else if(( state & NET::MaxHoriz ) == NET::MaxHoriz )
919  resize( desk.width(), size.height() );
920  else if(( state & NET::MaxVert ) == NET::MaxVert )
921  resize( size.width(), desk.height() );
922  else
923  resize( size );
924  // QWidget::showMaximized() is both insufficient and broken
925  KWindowSystem::setState( winId(), state );
926 #else
927  if (size.width() > desk.width() || size.height() > desk.height())
928  setWindowState( Qt::WindowMaximized );
929  else
930  resize( size );
931 #endif
932  }
933  }
934 }
935 #endif
936 
937 bool KMainWindow::initialGeometrySet() const
938 {
939  K_D(const KMainWindow);
940  return d->care_about_geometry;
941 }
942 
943 void KMainWindow::ignoreInitialGeometry()
944 {
945  K_D(KMainWindow);
946  d->care_about_geometry = false;
947 }
948 
949 void KMainWindow::setSettingsDirty()
950 {
951  K_D(KMainWindow);
952  d->setSettingsDirty();
953 }
954 
955 bool KMainWindow::settingsDirty() const
956 {
957  K_D(const KMainWindow);
958  return d->settingsDirty;
959 }
960 
961 void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize )
962 {
963  setAutoSaveSettings(KConfigGroup(KGlobal::config(), groupName), saveWindowSize);
964 }
965 
966 void KMainWindow::setAutoSaveSettings( const KConfigGroup & group,
967  bool saveWindowSize )
968 {
969  K_D(KMainWindow);
970  d->autoSaveSettings = true;
971  d->autoSaveGroup = group;
972  d->autoSaveWindowSize = saveWindowSize;
973 
974  if (!saveWindowSize && d->sizeTimer) {
975  d->sizeTimer->stop();
976  }
977 
978  // Now read the previously saved settings
979  applyMainWindowSettings(d->autoSaveGroup);
980 }
981 
982 void KMainWindow::resetAutoSaveSettings()
983 {
984  K_D(KMainWindow);
985  d->autoSaveSettings = false;
986  if (d->settingsTimer) {
987  d->settingsTimer->stop();
988  }
989 }
990 
991 bool KMainWindow::autoSaveSettings() const
992 {
993  K_D(const KMainWindow);
994  return d->autoSaveSettings;
995 }
996 
997 QString KMainWindow::autoSaveGroup() const
998 {
999  K_D(const KMainWindow);
1000  return d->autoSaveSettings ? d->autoSaveGroup.name() : QString();
1001 }
1002 
1003 KConfigGroup KMainWindow::autoSaveConfigGroup() const
1004 {
1005  K_D(const KMainWindow);
1006  return d->autoSaveSettings ? d->autoSaveGroup : KConfigGroup();
1007 }
1008 
1009 void KMainWindow::saveAutoSaveSettings()
1010 {
1011  K_D(KMainWindow);
1012  Q_ASSERT( d->autoSaveSettings );
1013  //kDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings";
1014  saveMainWindowSettings(d->autoSaveGroup);
1015  d->autoSaveGroup.sync();
1016  d->settingsDirty = false;
1017 }
1018 
1019 bool KMainWindow::event( QEvent* ev )
1020 {
1021  K_D(KMainWindow);
1022  switch( ev->type() ) {
1023 #ifdef Q_WS_WIN
1024  case QEvent::Move:
1025 #endif
1026  case QEvent::Resize:
1027  d->setSizeDirty();
1028  break;
1029  case QEvent::Polish:
1030  d->polish(this);
1031  break;
1032  case QEvent::ChildPolished:
1033  {
1034  QChildEvent *event = static_cast<QChildEvent*>(ev);
1035  QDockWidget *dock = qobject_cast<QDockWidget*>(event->child());
1036  KToolBar *toolbar = qobject_cast<KToolBar*>(event->child());
1037  QMenuBar *menubar = qobject_cast<QMenuBar*>(event->child());
1038  if (dock) {
1039  connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
1040  this, SLOT(setSettingsDirty()));
1041  connect(dock, SIGNAL(visibilityChanged(bool)),
1042  this, SLOT(setSettingsDirty()), Qt::QueuedConnection);
1043  connect(dock, SIGNAL(topLevelChanged(bool)),
1044  this, SLOT(setSettingsDirty()));
1045 
1046  // there is no signal emitted if the size of the dock changes,
1047  // hence install an event filter instead
1048  dock->installEventFilter(k_ptr->dockResizeListener);
1049  } else if (toolbar) {
1050  // there is no signal emitted if the size of the toolbar changes,
1051  // hence install an event filter instead
1052  toolbar->installEventFilter(k_ptr->dockResizeListener);
1053  } else if (menubar) {
1054  // there is no signal emitted if the size of the menubar changes,
1055  // hence install an event filter instead
1056  menubar->installEventFilter(k_ptr->dockResizeListener);
1057  }
1058  }
1059  break;
1060  case QEvent::ChildRemoved:
1061  {
1062  QChildEvent *event = static_cast<QChildEvent*>(ev);
1063  QDockWidget *dock = qobject_cast<QDockWidget*>(event->child());
1064  KToolBar *toolbar = qobject_cast<KToolBar*>(event->child());
1065  QMenuBar *menubar = qobject_cast<QMenuBar*>(event->child());
1066  if (dock) {
1067  disconnect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
1068  this, SLOT(setSettingsDirty()));
1069  disconnect(dock, SIGNAL(visibilityChanged(bool)),
1070  this, SLOT(setSettingsDirty()));
1071  disconnect(dock, SIGNAL(topLevelChanged(bool)),
1072  this, SLOT(setSettingsDirty()));
1073  dock->removeEventFilter(k_ptr->dockResizeListener);
1074  } else if (toolbar) {
1075  toolbar->removeEventFilter(k_ptr->dockResizeListener);
1076  } else if (menubar) {
1077  menubar->removeEventFilter(k_ptr->dockResizeListener);
1078  }
1079  }
1080  break;
1081  default:
1082  break;
1083  }
1084  return QMainWindow::event( ev );
1085 }
1086 
1087 bool KMainWindow::hasMenuBar()
1088 {
1089  return internalMenuBar(this);
1090 }
1091 
1092 KMenuBar *KMainWindow::menuBar()
1093 {
1094  KMenuBar * mb = internalMenuBar(this);
1095  if ( !mb ) {
1096  mb = new KMenuBar( this );
1097  // trigger a re-layout and trigger a call to the private
1098  // setMenuBar method.
1099  setMenuBar(mb);
1100  }
1101  return mb;
1102 }
1103 
1104 KStatusBar *KMainWindow::statusBar()
1105 {
1106  KStatusBar * sb = internalStatusBar(this);
1107  if ( !sb ) {
1108  sb = new KStatusBar( this );
1109  // trigger a re-layout and trigger a call to the private
1110  // setStatusBar method.
1111  setStatusBar(sb);
1112  }
1113  return sb;
1114 }
1115 
1116 void KMainWindowPrivate::_k_shuttingDown()
1117 {
1118  // Needed for Qt <= 3.0.3 at least to prevent reentrancy
1119  // when queryExit() shows a dialog. Check before removing!
1120  static bool reentrancy_protection = false;
1121  if (!reentrancy_protection)
1122  {
1123  reentrancy_protection = true;
1124  shuttingDown = true;
1125  // call the virtual queryExit
1126  q->queryExit();
1127  reentrancy_protection = false;
1128  }
1129 }
1130 
1131 void KMainWindowPrivate::_k_slotSettingsChanged(int category)
1132 {
1133  Q_UNUSED(category);
1134 
1135  // This slot will be called when the style KCM changes settings that need
1136  // to be set on the already running applications.
1137 
1138  // At this level (KMainWindow) the only thing we need to restore is the
1139  // animations setting (whether the user wants builtin animations or not).
1140 
1141  q->setAnimated(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects);
1142 }
1143 
1144 void KMainWindowPrivate::_k_slotSaveAutoSaveSize()
1145 {
1146  if (autoSaveGroup.isValid()) {
1147  q->saveWindowSize(autoSaveGroup);
1148  }
1149 }
1150 
1151 KToolBar *KMainWindow::toolBar( const QString& name )
1152 {
1153  QString childName = name;
1154  if (childName.isEmpty())
1155  childName = "mainToolBar";
1156 
1157  KToolBar *tb = findChild<KToolBar*>(childName);
1158  if ( tb )
1159  return tb;
1160 
1161  KToolBar* toolbar = new KToolBar(childName, this); // non-XMLGUI toolbar
1162  return toolbar;
1163 }
1164 
1165 QList<KToolBar*> KMainWindow::toolBars() const
1166 {
1167  QList<KToolBar*> ret;
1168 
1169  foreach (QObject* child, children())
1170  if (KToolBar* toolBar = qobject_cast<KToolBar*>(child))
1171  ret.append(toolBar);
1172 
1173  return ret;
1174 }
1175 
1176 QList<KMainWindow*> KMainWindow::memberList() { return *sMemberList; }
1177 
1178 QString KMainWindow::dbusName() const
1179 {
1180  return k_func()->dbusName;
1181 }
1182 
1183 #include "kmainwindow.moc"
1184 
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Tue Jul 23 2013 20:33:58 by doxygen 1.8.1.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.10.5 API Reference

Skip menu "kdelibs-4.10.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal