KDELibs4Support

kdialog.cpp
1 /* This file is part of the KDE Libraries
2  * Copyright (C) 1998 Thomas Tanghus ([email protected])
3  * Additions 1999-2000 by Espen Sand ([email protected])
4  * by Holger Freyther <[email protected]>
5  * 2005-2009 by Olivier Goffart (ogoffart at kde.org)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include "kdialog.h"
24 #include "kdialog_p.h"
25 #include <kglobal.h> // remove KGlobal::caption once done by QPA
26 
27 #include <QApplication>
28 #include <QDesktopWidget>
29 #include <QDialogButtonBox>
30 #include <QHBoxLayout>
31 #include <QHideEvent>
32 #include <QPointer>
33 #include <QStyle>
34 #include <QTimer>
35 #include <QVBoxLayout>
36 #include <QWhatsThis>
37 #include <QDebug>
38 
39 #include <kconfig.h>
40 #include <klocalizedstring.h>
41 #include <kpushbutton.h>
42 #include <kseparator.h>
43 #include <kstandardguiitem.h>
44 #include <khelpclient.h>
45 #include <kurllabel.h>
46 #include <kwindowconfig.h>
47 
48 #include <config-kdelibs4support.h>
49 
50 #if HAVE_X11
51 #include <qx11info_x11.h>
52 #include <netwm.h>
53 #endif
54 
55 static bool sAllowEmbeddingInGraphicsView = false;
56 
57 void KDialogPrivate::setupLayout()
58 {
59  Q_Q(KDialog);
60  if (!dirty) {
61  QMetaObject::invokeMethod(q, "queuedLayoutUpdate", Qt::QueuedConnection);
62  dirty = true;
63  }
64 }
65 
66 void KDialogPrivate::queuedLayoutUpdate()
67 {
68  if (!dirty) {
69  return;
70  }
71 
72  dirty = false;
73 
74  Q_Q(KDialog);
75 
76  // Don't lose the focus widget when re-creating the layout.
77  // Testcase: KOrganizer's "Select Categories" dialog
78  QPointer<QWidget> focusWidget = mMainWidget ? mMainWidget->focusWidget() : nullptr;
79 
80  if (q->layout() && q->layout() != mTopLayout) {
81  qWarning() << q->metaObject()->className() << "created with a layout; don't do that, KDialog takes care of it, use mainWidget or setMainWidget instead";
82  delete q->layout();
83  }
84 
85  delete mTopLayout;
86 
87  if (mButtonOrientation == Qt::Horizontal) {
88  mTopLayout = new QVBoxLayout(q);
89  } else {
90  mTopLayout = new QHBoxLayout(q);
91  }
92 
93  if (mUrlHelp) {
94  mTopLayout->addWidget(mUrlHelp, 0, Qt::AlignRight);
95  }
96 
97  if (mMainWidget) {
98  mTopLayout->addWidget(mMainWidget, 10);
99  }
100 
101  if (mDetailsWidget) {
102  mTopLayout->addWidget(mDetailsWidget);
103  }
104 
105  if (mActionSeparator) {
106  mTopLayout->addWidget(mActionSeparator);
107  }
108 
109  if (mButtonBox) {
110  mButtonBox->setOrientation(mButtonOrientation);
111  mTopLayout->addWidget(mButtonBox);
112  }
113 
114  if (focusWidget) {
115  focusWidget->setFocus();
116  }
117 }
118 
119 void KDialogPrivate::appendButton(KDialog::ButtonCode key, const KGuiItem &item)
120 {
121  Q_Q(KDialog);
122 
124  switch (key) {
125  case KDialog::Help:
126  case KDialog::Details:
128  break;
129  case KDialog::Default:
130  case KDialog::Reset:
132  break;
133  case KDialog::Ok:
135  break;
136  case KDialog::Apply:
138  break;
139  case KDialog::Try:
140  case KDialog::Yes:
142  break;
143  case KDialog::Close:
144  case KDialog::Cancel:
146  break;
147  case KDialog::No:
149  break;
150  case KDialog::User1:
151  case KDialog::User2:
152  case KDialog::User3:
154  break;
155  default:
157  break;
158  }
159 
160  if (role == QDialogButtonBox::InvalidRole) {
161  return;
162  }
163 
164  KPushButton *button = new KPushButton;
165  KGuiItem::assign(button, item);
166  mButtonBox->addButton(button, role);
167 
168  mButtonList.insert(key, button);
169  mButtonSignalMapper.setMapping(button, key);
170 
171  QObject::connect(button, SIGNAL(clicked()),
172  &mButtonSignalMapper, SLOT(map()));
173 
174  if (key == mDefaultButton) {
175  // Now that it exists, set it as default
176  q->setDefaultButton(mDefaultButton);
177  }
178 }
179 
180 void KDialogPrivate::init(KDialog *q)
181 {
182  q_ptr = q;
183 
184  dirty = false;
185 
188 
189  q->connect(&mButtonSignalMapper, SIGNAL(mapped(int)), q, SLOT(slotButtonClicked(int)));
190 
191  q->setPlainCaption(KGlobal::caption()); // set appropriate initial window title for case it gets not set later
192 }
193 
194 void KDialogPrivate::helpLinkClicked()
195 {
196  q_ptr->slotButtonClicked(KDialog::Help);
197 }
198 
200  : QDialog(parent, sAllowEmbeddingInGraphicsView ? flags : flags | Qt::BypassGraphicsProxyWidget), d_ptr(new KDialogPrivate)
201 {
202  d_ptr->init(this);
203 }
204 
205 KDialog::KDialog(KDialogPrivate &dd, QWidget *parent, Qt::WindowFlags flags)
206  : QDialog(parent, sAllowEmbeddingInGraphicsView ? flags : flags | Qt::BypassGraphicsProxyWidget), d_ptr(&dd)
207 {
208  d_ptr->init(this);
209 }
210 
212 {
213  delete d_ptr;
214 }
215 
217 {
218  Q_D(KDialog);
219  if (d->mButtonBox) {
220  d->mButtonList.clear();
221 
222  delete d->mButtonBox;
223  d->mButtonBox = nullptr;
224  }
225 
226  if (buttonMask & Cancel) {
227  buttonMask &= ~Close;
228  }
229 
230  if (buttonMask & Apply) {
231  buttonMask &= ~Try;
232  }
233 
234  if (buttonMask & Details) {
235  buttonMask &= ~Default;
236  }
237 
238  if (buttonMask == None) {
239  d->setupLayout();
240  return; // When we want no button box
241  }
242 
243  d->mEscapeButton = (buttonMask & Cancel) ? Cancel : Close;
244  d->mButtonBox = new QDialogButtonBox(this);
245 
246  if (buttonMask & Help) {
247  d->appendButton(Help, KStandardGuiItem::help());
248  }
249  if (buttonMask & Default) {
250  d->appendButton(Default, KStandardGuiItem::defaults());
251  }
252  if (buttonMask & Reset) {
253  d->appendButton(Reset, KStandardGuiItem::reset());
254  }
255  if (buttonMask & User3) {
256  d->appendButton(User3, KGuiItem());
257  }
258  if (buttonMask & User2) {
259  d->appendButton(User2, KGuiItem());
260  }
261  if (buttonMask & User1) {
262  d->appendButton(User1, KGuiItem());
263  }
264  if (buttonMask & Ok) {
265  d->appendButton(Ok, KStandardGuiItem::ok());
266  }
267  if (buttonMask & Apply) {
268  d->appendButton(Apply, KStandardGuiItem::apply());
269  }
270  if (buttonMask & Try) {
271  d->appendButton(Try, KGuiItem(i18n("&Try")));
272  }
273  if (buttonMask & Cancel) {
274  d->appendButton(Cancel, KStandardGuiItem::cancel());
275  }
276  if (buttonMask & Close) {
277  d->appendButton(Close, KStandardGuiItem::close());
278  }
279  if (buttonMask & Yes) {
280  d->appendButton(Yes, KStandardGuiItem::yes());
281  }
282  if (buttonMask & No) {
283  d->appendButton(No, KStandardGuiItem::no());
284  }
285  if (buttonMask & Details) {
286  d->appendButton(Details, KGuiItem(QString(), "help-about"));
288  }
289 
290  d->setupLayout();
291 }
292 
294 {
295  Q_D(KDialog);
296  if (d->mButtonOrientation != orientation) {
297  d->mButtonOrientation = orientation;
298 
299  if (d->mActionSeparator) {
300  d->mActionSeparator->setOrientation(d->mButtonOrientation);
301  }
302 
303  if (d->mButtonOrientation == Qt::Vertical) {
304  enableLinkedHelp(false); // 2000-06-18 Espen: No support for this yet.
305  }
306  }
307 }
308 
310 {
311  d_func()->mEscapeButton = id;
312 }
313 
314 void KDialog::setDefaultButton(ButtonCode newDefaultButton)
315 {
316  Q_D(KDialog);
317 
318  if (newDefaultButton == None) {
319  newDefaultButton = NoDefault; // #148969
320  }
321 
322  const KDialog::ButtonCode oldDefault = defaultButton();
323 
324  bool oldDefaultHadFocus = false;
325 
326  if (oldDefault != NoDefault) {
327  QPushButton *old = button(oldDefault);
328  if (old) {
329  oldDefaultHadFocus = (focusWidget() == old);
330  old->setDefault(false);
331  }
332  }
333 
334  if (newDefaultButton != NoDefault) {
335  QPushButton *b = button(newDefaultButton);
336  if (b) {
337  b->setDefault(true);
338  if (focusWidget() == nullptr || oldDefaultHadFocus) {
339  // No widget had focus yet, or the old default button had
340  // -> ok to give focus to the new default button, so that it's
341  // really default (Enter triggers it).
342  // But we don't do this if the kdialog user gave focus to a
343  // specific widget in the dialog.
344  b->setFocus();
345  }
346  }
347  }
348  d->mDefaultButton = newDefaultButton;
349  Q_ASSERT(defaultButton() == newDefaultButton);
350 }
351 
353 {
354  Q_D(const KDialog);
355  QHashIterator<int, KPushButton *> it(d->mButtonList);
356  while (it.hasNext()) {
357  it.next();
358  if (it.value()->isDefault()) {
359  return (ButtonCode)it.key();
360  }
361  }
362 
363  return d->mDefaultButton;
364 }
365 
367 {
368  Q_D(KDialog);
369  if (d->mMainWidget == widget) {
370  return;
371  }
372  d->mMainWidget = widget;
373  if (d->mMainWidget && d->mMainWidget->layout()) {
374  // Avoid double-margin problem
375  d->mMainWidget->layout()->setContentsMargins(0, 0, 0, 0);
376  }
377  d->setupLayout();
378 }
379 
381 {
382  Q_D(KDialog);
383  if (!d->mMainWidget) {
384  setMainWidget(new QWidget(this));
385  }
386  return d->mMainWidget;
387 }
388 
390 {
391  Q_D(const KDialog);
392 
393  if (!d->mMinSize.isEmpty()) {
394  return d->mMinSize.expandedTo(minimumSizeHint()) + d->mIncSize;
395  } else {
396  if (d->dirty) {
397  const_cast<KDialogPrivate *>(d)->queuedLayoutUpdate();
398  }
399  return QDialog::sizeHint() + d->mIncSize;
400  }
401 }
402 
404 {
405  Q_D(const KDialog);
406 
407  if (d->dirty) {
408  const_cast<KDialogPrivate *>(d)->queuedLayoutUpdate();
409  }
410  return QDialog::minimumSizeHint() + d->mIncSize;
411 }
412 
413 //
414 // Grab QDialogs keypresses if non-modal.
415 //
417 {
418  Q_D(KDialog);
419  if (event->modifiers() == 0) {
420  if (event->key() == Qt::Key_F1) {
421  QPushButton *button = this->button(Help);
422 
423  if (button) {
424  button->animateClick();
425  event->accept();
426  return;
427  }
428  }
429 
430  if (event->key() == Qt::Key_Escape) {
431  QPushButton *button = this->button(d->mEscapeButton);
432 
433  if (button) {
434  button->animateClick();
435  event->accept();
436  return;
437  }
438 
439  }
440  } else if (event->key() == Qt::Key_F1 && event->modifiers() == Qt::ShiftModifier) {
442  event->accept();
443  return;
444  } else if (event->modifiers() == Qt::ControlModifier &&
445  (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)) {
446  // accept the dialog when Ctrl-Return is pressed
447  QPushButton *button = this->button(Ok);
448 
449  if (button) {
450  button->animateClick();
451  event->accept();
452  return;
453  }
454  }
455 
457 }
458 
460 {
462 }
463 
465 {
467 }
468 
470 {
472 }
473 
475  QWidget *window,
476  CaptionFlags flags)
477 {
478  Q_UNUSED(window);
480  QString captionString = userCaption.isEmpty() ? caption : userCaption;
481 
482  // If the document is modified, add '[modified]'.
483  if (flags & ModifiedCaption) {
484  captionString += QString::fromUtf8(" [") + i18n("modified") + QString::fromUtf8("]");
485  }
486 
487  if (!userCaption.isEmpty()) {
488  // Add the application name if:
489  // User asked for it, it's not a duplication and the app name (caption()) is not empty
490  if (flags & AppNameCaption &&
491  !caption.isEmpty() &&
492  !userCaption.endsWith(caption)) {
493  // TODO: check to see if this is a transient/secondary window before trying to add the app name
494  // on platforms that need this
495  captionString += i18nc("Document/application separator in titlebar", " – ") + caption;
496  }
497  }
498 
499  return captionString;
500 }
501 
502 void KDialog::setCaption(const QString &_caption)
503 {
504  const QString caption = makeStandardCaption(_caption, this);
506 }
507 
508 void KDialog::setCaption(const QString &caption, bool modified)
509 {
510  CaptionFlags flags = HIGCompliantCaption;
511 
512  // ### Qt5 TODO: port to [*], see QWidget::setWindowFilePath
513  if (modified) {
514  flags |= ModifiedCaption;
515  }
516 
518 }
519 
521 {
522  if (QWidget *win = window()) {
523  win->setWindowTitle(caption);
524 #if HAVE_X11
525  if (QGuiApplication::platformName() == QStringLiteral("xcb")) {
526  NETWinInfo info(QX11Info::connection(), win->winId(), QX11Info::appRootWindow(), NET::Properties{}, NET::Properties2{});
527  info.setName(caption.toUtf8().constData());
528  }
529 #endif
530  }
531 }
532 
533 void KDialog::resizeLayout(QWidget *widget, int margin, int spacing) //static
534 {
535  if (widget->layout()) {
536  resizeLayout(widget->layout(), margin, spacing);
537  }
538 
539  if (widget->children().count() > 0) {
540  const QList<QObject *> list = widget->children();
541  foreach (QObject *object, list) {
542  if (object->isWidgetType()) {
543  resizeLayout((QWidget *)object, margin, spacing);
544  }
545  }
546  }
547 }
548 
549 void KDialog::resizeLayout(QLayout *layout, int margin, int spacing) //static
550 {
551  QLayoutItem *child;
552  int pos = 0;
553 
554  while ((child = layout->itemAt(pos))) {
555  if (child->layout()) {
556  resizeLayout(child->layout(), margin, spacing);
557  }
558 
559  ++pos;
560  }
561 
562  if (layout->layout()) {
563  layout->layout()->setMargin(margin);
564  layout->layout()->setSpacing(spacing);
565  }
566 }
567 
568 static QRect screenRect(QWidget *widget, int screen)
569 {
571  KConfig gc("kdeglobals", KConfig::NoGlobals);
572  KConfigGroup cg(&gc, "Windows");
573  if (desktop->isVirtualDesktop() &&
574  cg.readEntry("XineramaEnabled", true) &&
575  cg.readEntry("XineramaPlacementEnabled", true)) {
576 
577  if (screen < 0 || screen >= desktop->numScreens()) {
578  if (screen == -1) {
579  screen = desktop->primaryScreen();
580  } else if (screen == -3) {
581  screen = desktop->screenNumber(QCursor::pos());
582  } else {
583  screen = desktop->screenNumber(widget);
584  }
585  }
586 
587  return desktop->availableGeometry(screen);
588  } else {
589  return desktop->geometry();
590  }
591 }
592 
593 void KDialog::centerOnScreen(QWidget *widget, int screen)
594 {
595  if (!widget) {
596  return;
597  }
598 
599 #if HAVE_X11
600  if (QGuiApplication::platformName() == QStringLiteral("xcb")
601  && !(widget->windowFlags() & Qt::X11BypassWindowManagerHint) && widget->windowType() != Qt::Popup
602  && NETRootInfo(QX11Info::connection(), NET::Supported).isSupported(NET::WM2FullPlacement)) {
603  return; // the WM can handle placement much better
604  }
605 #endif
606 
607  QRect rect = screenRect(widget, screen);
608 
609  widget->move(rect.center().x() - widget->width() / 2,
610  rect.center().y() - widget->height() / 2);
611 }
612 
613 bool KDialog::avoidArea(QWidget *widget, const QRect &area, int screen)
614 {
615  if (!widget) {
616  return false;
617  }
618 
619  QRect fg = widget->frameGeometry();
620  if (!fg.intersects(area)) {
621  return true; // nothing to do.
622  }
623 
624  const QRect scr = screenRect(widget, screen);
625  QRect avoid(area); // let's add some margin
626  avoid.translate(-5, -5);
627  avoid.setRight(avoid.right() + 10);
628  avoid.setBottom(avoid.bottom() + 10);
629 
630  if (qMax(fg.top(), avoid.top()) <= qMin(fg.bottom(), avoid.bottom())) {
631  // We need to move the widget up or down
632  int spaceAbove = qMax(0, avoid.top() - scr.top());
633  int spaceBelow = qMax(0, scr.bottom() - avoid.bottom());
634  if (spaceAbove > spaceBelow) // where's the biggest side?
635  if (fg.height() <= spaceAbove) { // big enough?
636  fg.setY(avoid.top() - fg.height());
637  } else {
638  return false;
639  }
640  else if (fg.height() <= spaceBelow) { // big enough?
641  fg.setY(avoid.bottom());
642  } else {
643  return false;
644  }
645  }
646 
647  if (qMax(fg.left(), avoid.left()) <= qMin(fg.right(), avoid.right())) {
648  // We need to move the widget left or right
649  const int spaceLeft = qMax(0, avoid.left() - scr.left());
650  const int spaceRight = qMax(0, scr.right() - avoid.right());
651  if (spaceLeft > spaceRight) // where's the biggest side?
652  if (fg.width() <= spaceLeft) { // big enough?
653  fg.setX(avoid.left() - fg.width());
654  } else {
655  return false;
656  }
657  else if (fg.width() <= spaceRight) { // big enough?
658  fg.setX(avoid.right());
659  } else {
660  return false;
661  }
662  }
663 
664  widget->move(fg.x(), fg.y());
665 
666  return true;
667 }
668 
670 {
671  Q_D(KDialog);
672  if ((d->mActionSeparator != nullptr) == state) {
673  return;
674  }
675  if (state) {
676  if (d->mActionSeparator) {
677  return;
678  }
679 
680  d->mActionSeparator = new KSeparator(this);
681  d->mActionSeparator->setOrientation(d->mButtonOrientation);
682  } else {
683  delete d->mActionSeparator;
684  d->mActionSeparator = nullptr;
685  }
686 
687  d->setupLayout();
688 }
689 
691 {
692  d_func()->mMinSize = size;
693  adjustSize();
694 }
695 
697 {
698  d_func()->mIncSize = size;
699  adjustSize();
700 }
701 
703 {
704  Q_D(const KDialog);
705  return d->mButtonList.value(id, nullptr);
706 }
707 
708 void KDialog::enableButton(ButtonCode id, bool state)
709 {
710  QPushButton *button = this->button(id);
711  if (button) {
712  button->setEnabled(state);
713  }
714 }
715 
717 {
718  QPushButton *button = this->button(id);
719  if (button) {
720  return button->isEnabled();
721  }
722 
723  return false;
724 }
725 
726 void KDialog::enableButtonOk(bool state)
727 {
728  enableButton(Ok, state);
729 }
730 
732 {
733  enableButton(Apply, state);
734 }
735 
737 {
738  enableButton(Cancel, state);
739 }
740 
741 void KDialog::showButton(ButtonCode id, bool state)
742 {
743  QPushButton *button = this->button(id);
744  if (button) {
745  state ? button->show() : button->hide();
746  }
747 }
748 
750 {
751  QPushButton *button = this->button(id);
752  if (!button) {
753  return;
754  }
755 
756  KGuiItem::assign(button, item);
757 }
758 
759 void KDialog::setButtonMenu(ButtonCode id, QMenu *menu, ButtonPopupMode popupmode)
760 {
761  KPushButton *button = static_cast<KPushButton *>(this->button(id));
762  if (button) {
763  if (popupmode == InstantPopup) {
764  button->setMenu(menu);
765  } else {
766  button->setDelayedMenu(menu);
767  }
768  }
769 }
770 
772 {
773  Q_D(KDialog);
774  if (!d->mSettingDetails && (id == Details)) {
775  d->mDetailsButtonText = text;
776  setDetailsWidgetVisible(d->mDetailsVisible);
777  return;
778  }
779 
780  QPushButton *button = this->button(id);
781  if (button) {
782  button->setText(text);
783  }
784 }
785 
787 {
788  QPushButton *button = this->button(id);
789  if (button) {
790  return button->text();
791  } else {
792  return QString();
793  }
794 }
795 
797 {
798  QPushButton *button = this->button(id);
799  if (button) {
800  button->setIcon(icon);
801  }
802 }
803 
805 {
806  QPushButton *button = this->button(id);
807  if (button) {
808  return button->icon();
809  } else {
810  return QIcon();
811  }
812 }
813 
815 {
816  QPushButton *button = this->button(id);
817  if (button) {
818  if (text.isEmpty()) {
820  } else {
821  button->setToolTip(text);
822  }
823  }
824 }
825 
827 {
828  QPushButton *button = this->button(id);
829  if (button) {
830  return button->toolTip();
831  } else {
832  return QString();
833  }
834 }
835 
837 {
838  QPushButton *button = this->button(id);
839  if (button) {
840  if (text.isEmpty()) {
842  } else {
843  button->setWhatsThis(text);
844  }
845  }
846 }
847 
849 {
850  QPushButton *button = this->button(id);
851  if (button) {
852  return button->whatsThis();
853  } else {
854  return QString();
855  }
856 }
857 
859 {
860  QPushButton *button = this->button(id);
861  if (button) {
862  button->setFocus();
863  }
864 }
865 
866 void KDialog::setDetailsWidget(QWidget *detailsWidget)
867 {
868  Q_D(KDialog);
869  if (d->mDetailsWidget == detailsWidget) {
870  return;
871  }
872  delete d->mDetailsWidget;
873  d->mDetailsWidget = detailsWidget;
874 
875  if (d->mDetailsWidget->parentWidget() != this) {
876  d->mDetailsWidget->setParent(this);
877  }
878 
879  d->mDetailsWidget->hide();
880  d->setupLayout();
881 
882  if (!d->mSettingDetails) {
883  setDetailsWidgetVisible(d->mDetailsVisible);
884  }
885 }
886 
888 {
889  return d_func()->mDetailsVisible;
890 }
891 
893 {
894  Q_D(KDialog);
895  if (d->mDetailsButtonText.isEmpty()) {
896  d->mDetailsButtonText = i18n("&Details");
897  }
898 
899  d->mSettingDetails = true;
900  d->mDetailsVisible = visible;
901  if (d->mDetailsVisible) {
902  emit aboutToShowDetails();
903  setButtonText(Details, d->mDetailsButtonText + " <<");
904  if (d->mDetailsWidget) {
905  if (layout()) {
906  layout()->setEnabled(false);
907  }
908 
909  d->mDetailsWidget->show();
910 
911  adjustSize();
912 
913  if (layout()) {
914  layout()->activate();
915  layout()->setEnabled(true);
916  }
917  }
918  } else {
919  setButtonText(Details, d->mDetailsButtonText + " >>");
920  if (d->mDetailsWidget) {
921  d->mDetailsWidget->hide();
922  }
923 
924  if (layout()) {
925  layout()->activate();
926  adjustSize();
927  }
928 
929  }
930 
931  d->mSettingDetails = false;
932 }
933 
935 {
936  if (isVisible()) {
937  hide();
938  }
939 
940  deleteLater();
941 }
942 
944 {
945  Q_D(KDialog);
946  emit buttonClicked(static_cast<KDialog::ButtonCode>(button));
947 
948  switch (button) {
949  case Ok:
950  emit okClicked();
951  accept();
952  break;
953  case Apply:
954  emit applyClicked();
955  break;
956  case Try:
957  emit tryClicked();
958  break;
959  case User3:
960  emit user3Clicked();
961  break;
962  case User2:
963  emit user2Clicked();
964  break;
965  case User1:
966  emit user1Clicked();
967  break;
968  case Yes:
969  emit yesClicked();
970  done(Yes);
971  break;
972  case No:
973  emit noClicked();
974  done(No);
975  break;
976  case Cancel:
977  emit cancelClicked();
978  reject();
979  break;
980  case Close:
981  emit closeClicked();
982  done(Close); // KDE5: call reject() instead; more QDialog-like.
983  break;
984  case Help:
985  emit helpClicked();
986  if (!d->mAnchor.isEmpty() || !d->mHelpApp.isEmpty()) {
987  KHelpClient::invokeHelp(d->mAnchor, d->mHelpApp);
988  }
989  break;
990  case Default:
991  emit defaultClicked();
992  break;
993  case Reset:
994  emit resetClicked();
995  break;
996  case Details:
997  setDetailsWidgetVisible(!d->mDetailsVisible);
998  break;
999  }
1000 
1001  // If we're here from the closeEvent, and auto-delete is on, well, auto-delete now.
1002  if (d->mDeferredDelete) {
1003  d->mDeferredDelete = false;
1004  delayedDestruct();
1005  }
1006 }
1007 
1009 {
1010  Q_D(KDialog);
1011  if ((d->mUrlHelp != nullptr) == state) {
1012  return;
1013  }
1014  if (state) {
1015  if (d->mUrlHelp) {
1016  return;
1017  }
1018 
1019  d->mUrlHelp = new KUrlLabel(this);
1020  d->mUrlHelp->setText(helpLinkText());
1021  d->mUrlHelp->setFloatEnabled(true);
1022  d->mUrlHelp->setUnderline(true);
1023  d->mUrlHelp->setMinimumHeight(fontMetrics().height() + marginHint());
1024  connect(d->mUrlHelp, SIGNAL(leftClickedUrl()), SLOT(helpLinkClicked()));
1025 
1026  d->mUrlHelp->show();
1027  } else {
1028  delete d->mUrlHelp;
1029  d->mUrlHelp = nullptr;
1030  }
1031 
1032  d->setupLayout();
1033 }
1034 
1035 void KDialog::setHelp(const QString &anchor, const QString &appname)
1036 {
1037  Q_D(KDialog);
1038  d->mAnchor = anchor;
1039  d->mHelpApp = appname;
1040 }
1041 
1043 {
1044  Q_D(KDialog);
1045  d->mHelpLinkText = text;
1046  if (d->mUrlHelp) {
1047  d->mUrlHelp->setText(helpLinkText());
1048  }
1049 }
1050 
1052 {
1053  Q_D(const KDialog);
1054  return (d->mHelpLinkText.isEmpty() ? i18n("Get help...") : d->mHelpLinkText);
1055 }
1056 
1058 {
1059 }
1060 
1062 {
1063  emit hidden();
1064 
1065  if (!event->spontaneous()) {
1066  emit finished();
1067  }
1068 }
1069 
1071 {
1072  Q_D(KDialog);
1073  QPushButton *button = this->button(d->mEscapeButton);
1074  if (button && !isHidden()) {
1075  button->animateClick();
1076 
1078  // Don't let QWidget::close do a deferred delete just yet, wait for the click first
1079  d->mDeferredDelete = true;
1081  }
1082  } else {
1084  }
1085 }
1086 
1087 #ifndef KDELIBS4SUPPORT_NO_DEPRECATED
1089 {
1091 }
1092 #endif
1093 
1094 #ifndef KDELIBS4SUPPORT_NO_DEPRECATED
1096 {
1098 }
1099 #endif
1100 
1102 {
1103  sAllowEmbeddingInGraphicsView = allowEmbedding;
1104 }
1105 
1106 #include "moc_kdialog.cpp"
void setHelpLinkText(const QString &text)
Sets the text that is shown as the linked text.
Definition: kdialog.cpp:1042
void adjustSize()
QString helpLinkText() const
Returns the help link text.
Definition: kdialog.cpp:1051
Qt::Orientation orientation() const const
virtual QLayoutItem * itemAt(int index) const const=0
AlignRight
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
int screenNumber(const QWidget *widget) const const
void setWhatsThis(const QString &)
void setParent(QWidget *parent)
void showButtonSeparator(bool state)
Hide or display the a separator line drawn between the action buttons an the main widget.
Definition: kdialog.cpp:669
void saveDialogSize(KConfigGroup &config, KConfigGroup::WriteConfigFlags options=KConfigGroup::Normal) const
Saves the dialog's size dependent on the screen dimension either to the global or application config ...
Definition: kdialog.cpp:1095
QWidget * window() const const
void hidden()
The dialog is about to be hidden.
void aboutToShowDetails()
The detailsWidget is about to get shown.
void setMenu(QMenu *menu)
QWidget * mainWidget()
Definition: kdialog.cpp:380
QDesktopWidget * desktop()
QFontMetrics fontMetrics() const const
QWidget(QWidget *parent, Qt::WindowFlags f)
@ Apply
Show Apply button.
Definition: kdialog.h:141
QString fromUtf8(const char *str, int size)
virtual void reject()
virtual QLayout * layout() override
@ User3
Show User defined button 3.
Definition: kdialog.h:151
A QPushButton with drag-support and KGuiItem support.
Definition: kpushbutton.h:47
int right() const const
void setEscapeButton(ButtonCode id)
Sets the button that will be activated when the Escape key is pressed.
Definition: kdialog.cpp:309
void enableButtonCancel(bool state)
Enable or disable (gray out) the Cancel button.
Definition: kdialog.cpp:736
static int marginHint()
Returns the number of pixels that should be used between a dialog edge and the outermost widget(s) ac...
Definition: kdialog.cpp:459
void setMargin(int margin)
void setButtonWhatsThis(ButtonCode id, const QString &text)
Sets the "What's this?" text of any button.
Definition: kdialog.cpp:836
void setDetailsWidget(QWidget *detailsWidget)
Sets the widget that gets shown when "Details" is enabled.
Definition: kdialog.cpp:866
ButtonCode defaultButton() const
Returns the button code of the default button, or NoDefault if there is no default button.
Definition: kdialog.cpp:352
QLayout * layout() const const
void setButtonToolTip(ButtonCode id, const QString &text)
Sets the tooltip text of any button.
Definition: kdialog.cpp:814
virtual bool event(QEvent *event) override
ButtonCode
Definition: kdialog.h:136
QFontMetrics fontMetrics()
QFuture< typename QtPrivate::MapResultType< void, MapFunctor >::ResultType > mapped(const Sequence &sequence, MapFunctor function)
void setMainWidget(QWidget *widget)
Sets the main widget of the dialog.
Definition: kdialog.cpp:366
void user1Clicked()
The User1 button was pressed.
@ NoDefault
Used when specifying a default button; indicates that no button should be marked by default.
Definition: kdialog.h:152
void applyClicked()
The Apply button was pressed.
int width() const const
QScreen * screen() const const
int x() const const
int y() const const
@ Ok
Show Ok button. (this button accept()s the dialog; result set to QDialog::Accepted)
Definition: kdialog.h:140
@ No
Show No button. (this button closes the dialog and sets the result to KDialog::No)
Definition: kdialog.h:145
void setButtonMenu(ButtonCode id, QMenu *menu, ButtonPopupMode popupmode=InstantPopup)
Sets the menu of any button.
Definition: kdialog.cpp:759
void setAttribute(Qt::WidgetAttribute attribute, bool on)
QIcon buttonIcon(ButtonCode id) const
Returns the icon of any button.
Definition: kdialog.cpp:804
void setName(const char *name)
QString caption()
Returns a text for the window caption.
Definition: kglobal.cpp:175
virtual void closeEvent(QCloseEvent *e) override
void defaultClicked()
The Default button was pressed.
QPushButton * button(ButtonCode id) const
Returns the button that corresponds to the id.
Definition: kdialog.cpp:702
void user2Clicked()
The User2 button was pressed.
QString buttonWhatsThis(ButtonCode id) const
Returns the "What's this?" text of any button.
Definition: kdialog.cpp:848
const T & value() const const
@ User2
Show User defined button 2.
Definition: kdialog.h:150
bool isDetailsWidgetVisible() const
Returns the status of the Details button.
Definition: kdialog.cpp:887
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setEnabled(bool enable)
QWidget * focusWidget() const const
Qt::WindowType windowType() const const
int left() const const
void helpClicked()
The Help button was pressed.
void setButtonGuiItem(ButtonCode id, const KGuiItem &item)
Sets the KGuiItem directly for the button instead of using 3 methods to set the text,...
Definition: kdialog.cpp:749
void hide()
@ User1
Show User defined button 1.
Definition: kdialog.h:149
virtual int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const const=0
KGuiItem close()
void setButtonIcon(ButtonCode id, const QIcon &icon)
Sets the icon of any button.
Definition: kdialog.cpp:796
void setRight(int x)
KGuiItem cancel()
@ Details
Show Details button. (this button will show the detail widget set with setDetailsWidget)
Definition: kdialog.h:148
void setButtonText(ButtonCode id, const QString &text)
Sets the text of any button.
Definition: kdialog.cpp:771
typedef WindowFlags
bool intersects(const QRect &rectangle) const const
void deleteLater()
int bottom() const const
static void assign(QPushButton *button, const KGuiItem &item)
int top() const const
virtual QSize minimumSizeHint() const const override
const QRect availableGeometry(const QWidget *widget) const const
QString i18n(const char *text, const TYPE &arg...)
void restoreDialogSize(const KConfigGroup &config)
Restores the dialog's size from the configuration according to the screen size.
Definition: kdialog.cpp:1088
static QString makeStandardCaption(const QString &userCaption, QWidget *window=nullptr, CaptionFlags flags=HIGCompliantCaption)
Builds a caption that contains the application name along with the userCaption using a standard layou...
Definition: kdialog.cpp:474
int lineSpacing() const const
virtual QLayout * layout()
void enableButton(ButtonCode id, bool state)
Enable or disable (gray out) a general action button.
Definition: kdialog.cpp:708
void finished()
The dialog has finished.
void setBottom(int y)
QString buttonText(ButtonCode id) const
Returns the text of any button.
Definition: kdialog.cpp:786
void noClicked()
The No button was pressed.
void setDetailsWidgetVisible(bool visible)
Sets the status of the Details button.
Definition: kdialog.cpp:892
QHashIterator::Item next()
int numScreens() const const
static int groupSpacingHint()
Returns the number of pixels that should be used to visually separate groups of related options in a ...
Definition: kdialog.cpp:469
Horizontal
bool isEmpty() const const
QSize minimumSizeHint() const override
Reimplemented from QDialog.
Definition: kdialog.cpp:403
QByteArray toUtf8() const const
static void resizeLayout(QWidget *widget, int margin, int spacing)
Resize every layout manager used in widget and its nested children.
Definition: kdialog.cpp:533
virtual void accept()
KGuiItem yes()
QueuedConnection
void animateClick(int msec)
virtual void setPlainCaption(const QString &caption)
Make a plain caption without any modifications.
Definition: kdialog.cpp:520
A dialog base class with standard buttons and predefined layouts.
Definition: kdialog.h:128
KDialog(QWidget *parent=nullptr, Qt::WindowFlags flags={})
Creates a dialog.
Definition: kdialog.cpp:199
void incrementInitialSize(const QSize &size)
Convenience method.
Definition: kdialog.cpp:696
void okClicked()
The OK button was pressed.
virtual void done(int r)
void delayedDestruct()
Destruct the dialog delayed.
Definition: kdialog.cpp:934
void buttonClicked(KDialog::ButtonCode button)
A button has been pressed.
KSharedConfigPtr config()
Returns the general config object.
Definition: kglobal.cpp:102
QPoint pos()
bool testAttribute(Qt::WidgetAttribute attribute) const const
void setEnabled(bool)
PM_DefaultChildMargin
void show()
bool hasNext() const const
void closeEvent(QCloseEvent *e) override
Detects when a dialog is being closed from the window manager controls.
Definition: kdialog.cpp:1070
bool isButtonEnabled(ButtonCode id) const
Returns whether any button is enabled.
Definition: kdialog.cpp:716
bool isVirtualDesktop() const const
void setIcon(const QIcon &icon)
virtual void keyPressEvent(QKeyEvent *e) override
QWindow * windowHandle() const const
int height() const const
void setToolTip(const QString &)
void updateGeometry()
Updates the margins and spacings.
Definition: kdialog.cpp:1057
const char * constData() const const
static void centerOnScreen(QWidget *widget, int screen=-1)
Centers widget on the desktop, taking multi-head setups into account.
Definition: kdialog.cpp:593
bool isWidgetType() const const
KCONFIGGUI_EXPORT void restoreWindowSize(QWindow *window, const KConfigGroup &config)
QCA_EXPORT bool isSupported(const char *features, const QString &provider=QString())
void enterWhatsThisMode()
static int spacingHint()
Returns the number of pixels that should be used between widgets inside a dialog according to the KDE...
Definition: kdialog.cpp:464
void setButtonsOrientation(Qt::Orientation orientation)
Sets the orientation of the button box.
Definition: kdialog.cpp:293
~KDialog() override
Destroys the dialog.
Definition: kdialog.cpp:211
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
void setDefaultButton(ButtonCode id)
Sets the button that will be activated when the Enter key is pressed.
Definition: kdialog.cpp:314
void enableLinkedHelp(bool state)
Display or hide the help link area on the top of the dialog.
Definition: kdialog.cpp:1008
KGuiItem defaults()
void cancelClicked()
The Cancel button was pressed.
void setInitialSize(const QSize &size)
Convenience method.
Definition: kdialog.cpp:690
void setContentsMargins(int left, int top, int right, int bottom)
void yesClicked()
The Yes button was pressed.
void setButtonFocus(ButtonCode id)
Sets the focus to the button of the passed id.
Definition: kdialog.cpp:858
void setX(int x)
void setY(int y)
void setSpacing(int)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
KGuiItem reset()
void setDefault(bool)
void translate(int dx, int dy)
virtual void setCaption(const QString &caption)
Make a KDE compliant caption.
Definition: kdialog.cpp:502
void move(int x, int y)
@ Reset
Show Reset button.
Definition: kdialog.h:147
@ Cancel
Show Cancel-button. (this button reject()s the dialog; result set to QDialog::Rejected)
Definition: kdialog.h:143
void tryClicked()
The Try button was pressed.
@ Try
Show Try button.
Definition: kdialog.h:142
bool activate()
static bool avoidArea(QWidget *widget, const QRect &area, int screen=-1)
Places widget so that it doesn't cover a certain area of the screen.
Definition: kdialog.cpp:613
@ Yes
Show Yes button. (this button closes the dialog and sets the result to KDialog::Yes)
Definition: kdialog.h:146
void closeClicked()
The Close button was pressed.
void resetClicked()
The Reset button was pressed.
void user3Clicked()
The User3 button was pressed.
void setHelp(const QString &anchor, const QString &appname=QString())
Sets the help path and topic.
Definition: kdialog.cpp:1035
void invokeHelp(const QString &anchor=QString(), const QString &appname=QString())
bool isHidden() const const
void setButtons(ButtonCodes buttonMask)
Creates (or recreates) the button box and all the buttons in it.
Definition: kdialog.cpp:216
KGuiItem apply()
static void setAllowEmbeddingInGraphicsView(bool allowEmbedding)
Allow embedding the dialogs based on KDialog into a graphics view.
Definition: kdialog.cpp:1101
ShiftModifier
QSize sizeHint() const override
Reimplemented from QDialog.
Definition: kdialog.cpp:389
QFuture< void > map(Sequence &sequence, MapFunctor function)
QString buttonToolTip(ButtonCode id) const
Returns the tooltip of any button.
Definition: kdialog.cpp:826
@ Help
Show Help button. (this button will run the help set with setHelp)
Definition: kdialog.h:138
void setFocus()
void keyPressEvent(QKeyEvent *) override
Definition: kdialog.cpp:416
void enableButtonOk(bool state)
Enable or disable (gray out) the OK button.
Definition: kdialog.cpp:726
void hideEvent(QHideEvent *) override
Emits the hidden signal.
Definition: kdialog.cpp:1061
const Key & key() const const
void setText(const QString &text)
WA_DeleteOnClose
virtual void slotButtonClicked(int button)
Activated when the button button is clicked.
Definition: kdialog.cpp:943
@ Default
Show Default button.
Definition: kdialog.h:139
QStyle * style()
Q_D(Todo)
void showButton(ButtonCode id, bool state)
Hide or display a general action button.
Definition: kdialog.cpp:741
const QObjectList & children() const const
virtual QSize sizeHint() const const override
void enableButtonApply(bool state)
Enable or disable (gray out) the Apply button.
Definition: kdialog.cpp:731
KGuiItem help()
@ Close
Show Close-button. (this button closes the dialog)
Definition: kdialog.h:144
KCONFIGGUI_EXPORT void saveWindowSize(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options=KConfigGroup::Normal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Dec 7 2023 03:56:48 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.