kdelibs/kdeui/dialogs/kdialog.cpp
Ivailo Monev 0e0db0b815 kdeui: move session management to KApplicaiton
every comment about X11 and session management in general claims it was
broken, not going to claim otherwise. everything that does not use
KApplication shall not be involved into session management now and gets
the middle finger (SIGTERM or SIGKILL) after 5 sec by klauncher when the
session is done

also session management has to be explicitly enabled by applications
now, disabled by default

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2024-05-09 08:29:51 +03:00

1131 lines
29 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* This file is part of the KDE Libraries
* Copyright (C) 1998 Thomas Tanghus (tanghus@earthling.net)
* Additions 1999-2000 by Espen Sand (espen@kde.org)
* by Holger Freyther <freyther@kde.org>
* 2005-2009 by Olivier Goffart (ogoffart at kde.org)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "kdialog.h"
#include "kdialog_p.h"
#include <kdebug.h>
#include "kdialogqueue_p.h"
#include <config.h>
#include <QApplication>
#include <QDesktopWidget>
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QtGui/qevent.h>
#include <QPointer>
#include <QStyle>
#include <QTimer>
#include <QVBoxLayout>
#include <QWhatsThis>
#include <klocale.h>
#include <kpushbutton.h>
#include <kseparator.h>
#include <kstandardguiitem.h>
#include <ktoolinvocation.h>
#include <kurllabel.h>
#include <kwindowsystem.h>
#ifdef Q_WS_X11
#include <qx11info_x11.h>
#include <netwm.h>
#endif
static bool sAllowEmbeddingInGraphicsView = false;
void KDialogPrivate::setupLayout()
{
Q_Q(KDialog);
if (!dirty) {
QMetaObject::invokeMethod(q, "queuedLayoutUpdate", Qt::QueuedConnection);
dirty = true;
}
}
void KDialogPrivate::queuedLayoutUpdate()
{
if (!dirty) {
return;
}
dirty = false;
Q_Q(KDialog);
// Don't lose the focus widget when re-creating the layout.
// Testcase: KOrganizer's "Select Categories" dialog
QPointer<QWidget> focusWidget = mMainWidget ? mMainWidget->focusWidget() : 0;
if (q->layout() && q->layout() != mTopLayout) {
kWarning() << q->metaObject()->className() << "created with a layout; don't do that, KDialog takes care of it, use mainWidget or setMainWidget instead";
delete q->layout();
}
delete mTopLayout;
if (mButtonOrientation == Qt::Horizontal) {
mTopLayout = new QVBoxLayout(q);
} else {
mTopLayout = new QHBoxLayout(q);
}
if (mUrlHelp) {
mTopLayout->addWidget(mUrlHelp, 0, Qt::AlignRight);
}
if (mMainWidget) {
mTopLayout->addWidget(mMainWidget, 10);
}
if (mDetailsWidget) {
mTopLayout->addWidget(mDetailsWidget);
}
if (mActionSeparator) {
mTopLayout->addWidget(mActionSeparator);
}
if (mButtonBox) {
mButtonBox->setOrientation(mButtonOrientation);
mTopLayout->addWidget(mButtonBox);
}
if (focusWidget) {
focusWidget->setFocus();
}
}
void KDialogPrivate::appendButton(KDialog::ButtonCode key, const KGuiItem &item)
{
Q_Q(KDialog);
QDialogButtonBox::ButtonRole role = QDialogButtonBox::InvalidRole;
switch (key) {
case KDialog::Help:
case KDialog::Details:
role = QDialogButtonBox::HelpRole;
break;
case KDialog::Default:
case KDialog::Reset:
role = QDialogButtonBox::ResetRole;
break;
case KDialog::Ok:
role = QDialogButtonBox::AcceptRole;
break;
case KDialog::Apply:
role = QDialogButtonBox::ApplyRole;
break;
case KDialog::Try:
case KDialog::Yes:
role = QDialogButtonBox::YesRole;
break;
case KDialog::Close:
case KDialog::Cancel:
role = QDialogButtonBox::RejectRole;
break;
case KDialog::No:
role = QDialogButtonBox::NoRole;
break;
case KDialog::User1:
case KDialog::User2:
case KDialog::User3:
role = QDialogButtonBox::ActionRole;
break;
default:
role = QDialogButtonBox::InvalidRole;
break;
}
if (role == QDialogButtonBox::InvalidRole) {
return;
}
KPushButton *button = new KPushButton(item);
mButtonBox->addButton(button, role);
mButtonList.insert(key, button);
mButtonSignalMapper.setMapping(button, key);
QObject::connect(button, SIGNAL(clicked()), &mButtonSignalMapper, SLOT(map()));
if (key == mDefaultButton) {
// Now that it exists, set it as default
q->setDefaultButton(mDefaultButton);
}
}
void KDialogPrivate::init(KDialog *q)
{
q_ptr = q;
dirty = false;
q->setButtons(KDialog::Ok | KDialog::Cancel);
q->setDefaultButton(KDialog::Ok);
q->connect(&mButtonSignalMapper, SIGNAL(mapped(int)), q, SLOT(slotButtonClicked(int)));
q->setWindowTitle(KGlobal::caption()); // set appropriate initial window title for case it gets not set later
}
void KDialogPrivate::helpLinkClicked()
{
q_ptr->slotButtonClicked(KDialog::Help);
}
KDialog::KDialog(QWidget *parent, Qt::WindowFlags flags)
: QDialog(parent, sAllowEmbeddingInGraphicsView ? flags : flags | Qt::BypassGraphicsProxyWidget ),
d_ptr(new KDialogPrivate())
{
d_ptr->init(this);
}
KDialog::KDialog(KDialogPrivate &dd, QWidget *parent, Qt::WindowFlags flags)
: QDialog(parent, sAllowEmbeddingInGraphicsView ? flags : flags | Qt::BypassGraphicsProxyWidget),
d_ptr(&dd)
{
d_ptr->init(this);
}
KDialog::~KDialog()
{
delete d_ptr;
}
void KDialog::setButtons(ButtonCodes buttonMask)
{
Q_D(KDialog);
if (d->mButtonBox) {
d->mButtonList.clear();
delete d->mButtonBox;
d->mButtonBox = 0;
}
if (buttonMask & KDialog::Cancel) {
buttonMask &= ~KDialog::Close;
}
if (buttonMask & KDialog::Apply) {
buttonMask &= ~KDialog::Try;
}
if (buttonMask & KDialog::Details) {
buttonMask &= ~KDialog::Default;
}
if (buttonMask == KDialog::None) {
d->setupLayout();
return; // When we want no button box
}
d->mEscapeButton = (buttonMask & KDialog::Cancel) ? KDialog::Cancel : KDialog::Close;
d->mButtonBox = new QDialogButtonBox(this);
if (buttonMask & KDialog::Help) {
d->appendButton(KDialog::Help, KStandardGuiItem::help());
}
if (buttonMask & KDialog::Default) {
d->appendButton(KDialog::Default, KStandardGuiItem::defaults());
}
if (buttonMask & KDialog::Reset) {
d->appendButton(KDialog::Reset, KStandardGuiItem::reset());
}
if (buttonMask & KDialog::User3) {
d->appendButton(KDialog::User3, KGuiItem());
}
if (buttonMask & KDialog::User2) {
d->appendButton(KDialog::User2, KGuiItem());
}
if (buttonMask & KDialog::User1) {
d->appendButton(KDialog::User1, KGuiItem());
}
if (buttonMask & KDialog::Ok) {
d->appendButton(KDialog::Ok, KStandardGuiItem::ok());
}
if (buttonMask & KDialog::Apply) {
d->appendButton(KDialog::Apply, KStandardGuiItem::apply());
}
if (buttonMask & KDialog::Try) {
d->appendButton(KDialog::Try, KGuiItem(i18n("&Try")));
}
if (buttonMask & KDialog::Cancel) {
d->appendButton(KDialog::Cancel, KStandardGuiItem::cancel());
}
if (buttonMask & KDialog::Close) {
d->appendButton(KDialog::Close, KStandardGuiItem::close());
}
if (buttonMask & KDialog::Yes) {
d->appendButton(KDialog::Yes, KStandardGuiItem::yes());
}
if (buttonMask & KDialog::No) {
d->appendButton(KDialog::No, KStandardGuiItem::no());
}
if (buttonMask & KDialog::Details) {
d->appendButton(KDialog::Details, KGuiItem(QString(), "help-about"));
setDetailsWidgetVisible(false);
}
d->setupLayout();
}
void KDialog::setButtonsOrientation(Qt::Orientation orientation)
{
Q_D(KDialog);
if (d->mButtonOrientation != orientation) {
d->mButtonOrientation = orientation;
if (d->mActionSeparator) {
d->mActionSeparator->setOrientation(d->mButtonOrientation);
}
if (d->mButtonOrientation == Qt::Vertical) {
enableLinkedHelp(false); // 2000-06-18 Espen: No support for this yet.
}
}
}
void KDialog::setEscapeButton(ButtonCode id)
{
d_func()->mEscapeButton = id;
}
void KDialog::setDefaultButton(ButtonCode newDefaultButton)
{
Q_D(KDialog);
if (newDefaultButton == KDialog::None) {
newDefaultButton = KDialog::NoDefault; // #148969
}
const KDialog::ButtonCode oldDefault = defaultButton();
bool oldDefaultHadFocus = false;
if (oldDefault != KDialog::NoDefault) {
KPushButton *old = button(oldDefault);
if (old) {
oldDefaultHadFocus = (focusWidget() == old);
old->setDefault(false);
}
}
if (newDefaultButton != KDialog::NoDefault) {
KPushButton *b = button(newDefaultButton);
if (b) {
b->setDefault(true);
if (focusWidget() == 0 || oldDefaultHadFocus) {
// No widget had focus yet, or the old default button had
// -> ok to give focus to the new default button, so that it's
// really default (Enter triggers it).
// But we don't do this if the kdialog user gave focus to a
// specific widget in the dialog.
b->setFocus();
}
}
}
d->mDefaultButton = newDefaultButton;
Q_ASSERT(defaultButton() == newDefaultButton);
}
KDialog::ButtonCode KDialog::defaultButton() const
{
Q_D(const KDialog);
QHashIterator<int, KPushButton*> it(d->mButtonList);
while (it.hasNext()) {
it.next();
if (it.value()->isDefault()) {
return static_cast<KDialog::ButtonCode>(it.key());
}
}
return d->mDefaultButton;
}
void KDialog::setMainWidget(QWidget *widget)
{
Q_D(KDialog);
if (d->mMainWidget == widget) {
return;
}
d->mMainWidget = widget;
if (d->mMainWidget && d->mMainWidget->layout()) {
// Avoid double-margin problem
d->mMainWidget->layout()->setMargin(0);
}
d->setupLayout();
}
QWidget *KDialog::mainWidget()
{
Q_D(KDialog);
if (!d->mMainWidget) {
setMainWidget(new QWidget(this));
}
return d->mMainWidget;
}
QSize KDialog::sizeHint() const
{
Q_D(const KDialog);
if (!d->mMinSize.isEmpty()) {
return d->mMinSize.expandedTo( minimumSizeHint() ) + d->mIncSize;
}
if (d->dirty) {
const_cast<KDialogPrivate*>(d)->queuedLayoutUpdate();
}
return QDialog::sizeHint() + d->mIncSize;
}
QSize KDialog::minimumSizeHint() const
{
Q_D(const KDialog);
if (d->dirty) {
const_cast<KDialogPrivate*>(d)->queuedLayoutUpdate();
}
return QDialog::minimumSizeHint() + d->mIncSize;
}
//
// Grab QDialogs keypresses if non-modal.
//
void KDialog::keyPressEvent(QKeyEvent *event)
{
Q_D(KDialog);
if (event->modifiers() == 0) {
if (event->key() == Qt::Key_F1) {
KPushButton *button = this->button(KDialog::Help);
if (button) {
button->animateClick();
event->accept();
return;
}
}
if (event->key() == Qt::Key_Escape) {
KPushButton *button = this->button(d->mEscapeButton);
if (button) {
button->animateClick();
event->accept();
return;
}
}
} else if (event->key() == Qt::Key_F1 && event->modifiers() == Qt::ShiftModifier) {
QWhatsThis::enterWhatsThisMode();
event->accept();
return;
} else if (event->modifiers() == Qt::ControlModifier &&
(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter))
{
// accept the dialog when Ctrl-Return is pressed
KPushButton *button = this->button(KDialog::Ok);
if (button) {
button->animateClick();
event->accept();
return;
}
}
QDialog::keyPressEvent(event);
}
int KDialog::marginHint()
{
return QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin);
}
int KDialog::spacingHint()
{
return QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
}
int KDialog::groupSpacingHint()
{
return QApplication::fontMetrics().lineSpacing();
}
QString KDialog::makeStandardCaption(const QString &userCaption,
QWidget* window,
CaptionFlags flags)
{
Q_UNUSED(window);
QString caption = KGlobal::caption();
QString captionString = userCaption.isEmpty() ? caption : userCaption;
// If the document is modified, add '[modified]'.
if (flags & KDialog::ModifiedCaption) {
captionString += QString::fromUtf8(" [") + i18n("modified") + QString::fromUtf8("]");
}
if (!userCaption.isEmpty()) {
// Add the application name if:
// User asked for it, it's not a duplication and the app name (caption()) is not empty
if ( flags & AppNameCaption && !caption.isEmpty() && !userCaption.endsWith(caption)) {
// TODO: check to see if this is a transient/secondary window before trying to add the app name
// on platforms that need this
captionString += i18nc("Document/application separator in titlebar", " ") + caption;
}
}
return captionString;
}
void KDialog::setCaption(const QString &caption)
{
setWindowTitle(makeStandardCaption(caption, this));
}
void KDialog::setCaption(const QString &caption, bool modified)
{
CaptionFlags flags = HIGCompliantCaption;
if (modified) {
flags |= ModifiedCaption;
}
setWindowTitle(makeStandardCaption(caption, this, flags));
}
static QRect screenRect(QWidget *widget, int screen)
{
QDesktopWidget *desktop = QApplication::desktop();
KConfig gc("kdeglobals", KConfig::NoGlobals);
KConfigGroup cg(&gc, "Windows");
if (desktop->isVirtualDesktop() &&
cg.readEntry("XineramaEnabled", true) &&
cg.readEntry("XineramaPlacementEnabled", true))
{
if (screen < 0 || screen >= desktop->screenCount()) {
if (screen == -1) {
screen = desktop->primaryScreen();
} else if (screen == -3) {
screen = desktop->screenNumber(QCursor::pos());
} else {
screen = desktop->screenNumber(widget);
}
}
return desktop->availableGeometry(screen);
}
return desktop->geometry();
}
void KDialog::centerOnScreen( QWidget *widget, int screen )
{
if (!widget) {
return;
}
#ifdef Q_WS_X11
if( !(widget->windowFlags() & Qt::X11BypassWindowManagerHint ) && widget->windowType() != Qt::Popup
&& NETRootInfo(QX11Info::display(), NET::Supported).isSupported(NET::WM2FullPlacement)) {
return; // the WM can handle placement much better
}
#endif
const QRect rect = screenRect(widget, screen);
widget->move(
rect.center().x() - widget->width() / 2,
rect.center().y() - widget->height() / 2
);
}
bool KDialog::avoidArea(QWidget *widget, const QRect &area, int screen)
{
if (!widget) {
return false;
}
QRect fg = widget->frameGeometry();
if (!fg.intersects(area)) {
return true; // nothing to do.
}
const QRect scr = screenRect(widget, screen);
QRect avoid(area); // let's add some margin
avoid.translate(-5, -5);
avoid.setRight(avoid.right() + 10);
avoid.setBottom(avoid.bottom() + 10);
if (qMax(fg.top(), avoid.top()) <= qMin(fg.bottom(), avoid.bottom())) {
// We need to move the widget up or down
int spaceAbove = qMax( 0, avoid.top() - scr.top() );
int spaceBelow = qMax( 0, scr.bottom() - avoid.bottom() );
if ( spaceAbove > spaceBelow ) // where's the biggest side?
if ( fg.height() <= spaceAbove ) // big enough?
fg.setY( avoid.top() - fg.height() );
else
return false;
else
if ( fg.height() <= spaceBelow ) // big enough?
fg.setY( avoid.bottom() );
else
return false;
}
if (qMax(fg.left(), avoid.left()) <= qMin(fg.right(), avoid.right())) {
// We need to move the widget left or right
const int spaceLeft = qMax(0, avoid.left() - scr.left());
const int spaceRight = qMax(0, scr.right() - avoid.right());
if (spaceLeft > spaceRight) {
// where's the biggest side?
if (fg.width() <= spaceLeft) { // big enough?
fg.setX(avoid.left() - fg.width());
} else {
return false;
}
} else {
if (fg.width() <= spaceRight) { // big enough?
fg.setX( avoid.right());
} else {
return false;
}
}
}
widget->move(fg.x(), fg.y());
return true;
}
void KDialog::showButtonSeparator(bool state)
{
Q_D(KDialog);
if ((d->mActionSeparator != 0) == state) {
return;
}
if (state) {
if (d->mActionSeparator) {
return;
}
d->mActionSeparator = new KSeparator(this);
d->mActionSeparator->setOrientation(d->mButtonOrientation);
} else {
delete d->mActionSeparator;
d->mActionSeparator = 0;
}
d->setupLayout();
}
void KDialog::setInitialSize(const QSize &size)
{
d_func()->mMinSize = size;
adjustSize();
}
void KDialog::incrementInitialSize(const QSize &size)
{
d_func()->mIncSize = size;
adjustSize();
}
KPushButton* KDialog::button(ButtonCode id) const
{
Q_D(const KDialog);
return d->mButtonList.value(id, 0);
}
void KDialog::enableButton(ButtonCode id, bool state)
{
KPushButton *button = this->button(id);
if (button) {
button->setEnabled(state);
}
}
bool KDialog::isButtonEnabled(ButtonCode id) const
{
KPushButton *button = this->button(id);
if (button) {
return button->isEnabled();
}
return false;
}
void KDialog::enableButtonOk(bool state)
{
enableButton(KDialog::Ok, state);
}
void KDialog::enableButtonApply(bool state)
{
enableButton(KDialog::Apply, state);
}
void KDialog::enableButtonCancel(bool state)
{
enableButton(KDialog::Cancel, state);
}
void KDialog::showButton(ButtonCode id, bool state)
{
KPushButton *button = this->button(id);
if (button) {
state ? button->show() : button->hide();
}
}
void KDialog::setButtonGuiItem(ButtonCode id, const KGuiItem &item)
{
KPushButton *button = this->button(id);
if (!button) {
return;
}
button->setGuiItem(item);
}
void KDialog::setButtonMenu(ButtonCode id, QMenu *menu, ButtonPopupMode popupmode)
{
KPushButton *button = this->button(id);
if (button) {
if (popupmode == KDialog::InstantPopup) {
button->setMenu(menu);
} else {
button->setDelayedMenu(menu);
}
}
}
void KDialog::setButtonText(ButtonCode id, const QString &text)
{
Q_D(KDialog);
if (!d->mSettingDetails && (id == KDialog::Details)) {
d->mDetailsButtonText = text;
setDetailsWidgetVisible(d->mDetailsVisible);
return;
}
KPushButton *button = this->button(id);
if (button) {
button->setText(text);
}
}
QString KDialog::buttonText(ButtonCode id) const
{
KPushButton *button = this->button(id);
if (button) {
return button->text();
}
return QString();
}
void KDialog::setButtonIcon(ButtonCode id, const KIcon &icon)
{
KPushButton *button = this->button(id);
if (button) {
button->setIcon(icon);
}
}
KIcon KDialog::buttonIcon(ButtonCode id) const
{
KPushButton *button = this->button(id);
if (button) {
return KIcon(button->icon());
}
return KIcon();
}
void KDialog::setButtonToolTip( ButtonCode id, const QString &text)
{
KPushButton *button = this->button(id);
if (button) {
if (text.isEmpty()) {
button->setToolTip(QString());
} else {
button->setToolTip(text);
}
}
}
QString KDialog::buttonToolTip(ButtonCode id) const
{
KPushButton *button = this->button(id);
if (button) {
return button->toolTip();
}
return QString();
}
void KDialog::setButtonWhatsThis(ButtonCode id, const QString &text)
{
KPushButton *button = this->button(id);
if (button) {
if (text.isEmpty()) {
button->setWhatsThis(QString());
} else {
button->setWhatsThis(text);
}
}
}
QString KDialog::buttonWhatsThis(ButtonCode id) const
{
KPushButton *button = this->button(id);
if (button) {
return button->whatsThis();
}
return QString();
}
void KDialog::setButtonFocus(ButtonCode id)
{
KPushButton *button = this->button(id);
if (button) {
button->setFocus();
}
}
void KDialog::setDetailsWidget(QWidget *detailsWidget)
{
Q_D(KDialog);
if (d->mDetailsWidget == detailsWidget) {
return;
}
delete d->mDetailsWidget;
d->mDetailsWidget = detailsWidget;
if (d->mDetailsWidget->parentWidget() != this) {
d->mDetailsWidget->setParent(this);
}
d->mDetailsWidget->hide();
d->setupLayout();
if (!d->mSettingDetails) {
setDetailsWidgetVisible(d->mDetailsVisible);
}
}
bool KDialog::isDetailsWidgetVisible() const
{
return d_func()->mDetailsVisible;
}
void KDialog::setDetailsWidgetVisible(bool visible)
{
Q_D(KDialog);
if (d->mDetailsButtonText.isEmpty()) {
d->mDetailsButtonText = i18n("&Details");
}
d->mSettingDetails = true;
d->mDetailsVisible = visible;
if (d->mDetailsVisible) {
emit aboutToShowDetails();
setButtonText(KDialog::Details, d->mDetailsButtonText + " <<");
if (d->mDetailsWidget) {
if (layout()) {
layout()->setEnabled(false);
}
d->mDetailsWidget->show();
if (layout()) {
layout()->activate();
layout()->setEnabled(true);
if (layout()->sizeConstraint() == QLayout::SetFixedSize) {
adjustSize();
}
}
}
} else {
setButtonText(KDialog::Details, d->mDetailsButtonText + " >>");
if (d->mDetailsWidget) {
d->mDetailsWidget->hide();
}
if (layout()) {
layout()->activate();
if (layout()->sizeConstraint() == QLayout::SetFixedSize) {
adjustSize();
}
}
}
d->mSettingDetails = false;
}
void KDialog::delayedDestruct()
{
if (isVisible()) {
hide();
}
deleteLater();
}
void KDialog::slotButtonClicked(int button)
{
Q_D(KDialog);
emit buttonClicked(static_cast<KDialog::ButtonCode>(button));
switch(button) {
case KDialog::Ok: {
emit okClicked();
accept();
break;
}
case KDialog::Apply: {
emit applyClicked();
break;
}
case KDialog::Try: {
emit tryClicked();
break;
}
case KDialog::User3: {
emit user3Clicked();
break;
}
case KDialog::User2: {
emit user2Clicked();
break;
}
case KDialog::User1: {
emit user1Clicked();
break;
}
case KDialog::Yes: {
emit yesClicked();
done(KDialog::Yes);
break;
}
case KDialog::No: {
emit noClicked();
done(KDialog::No);
break;
}
case KDialog::Cancel: {
emit cancelClicked();
reject();
break;
}
case KDialog::Close: {
emit closeClicked();
done(KDialog::Close); // KDE5: call reject() instead; more QDialog-like.
break;
}
case KDialog::Help: {
emit helpClicked();
if (!d->mAnchor.isEmpty() || !d->mHelpApp.isEmpty()) {
KToolInvocation::self()->invokeHelp( d->mAnchor, d->mHelpApp);
}
break;
}
case KDialog::Default: {
emit defaultClicked();
break;
}
case KDialog::Reset: {
emit resetClicked();
break;
}
case KDialog::Details: {
setDetailsWidgetVisible(!d->mDetailsVisible);
break;
}
}
// If we're here from the closeEvent, and auto-delete is on, well, auto-delete now.
if (d->mDeferredDelete) {
d->mDeferredDelete = false;
delayedDestruct();
}
}
void KDialog::enableLinkedHelp(bool state)
{
Q_D(KDialog);
if ((d->mUrlHelp != 0) == state) {
return;
}
if (state) {
if (d->mUrlHelp) {
return;
}
d->mUrlHelp = new KUrlLabel(this);
d->mUrlHelp->setText(helpLinkText());
d->mUrlHelp->setFloatEnabled(true);
d->mUrlHelp->setUnderline(true);
d->mUrlHelp->setMinimumHeight( fontMetrics().height() + marginHint());
connect( d->mUrlHelp, SIGNAL(leftClickedUrl()), SLOT(helpLinkClicked()));
d->mUrlHelp->show();
} else {
delete d->mUrlHelp;
d->mUrlHelp = 0;
}
d->setupLayout();
}
void KDialog::setHelp(const QString &anchor, const QString &appname)
{
Q_D(KDialog);
d->mAnchor = anchor;
d->mHelpApp = appname;
}
void KDialog::setHelpLinkText(const QString &text)
{
Q_D(KDialog);
d->mHelpLinkText = text;
if (d->mUrlHelp) {
d->mUrlHelp->setText(helpLinkText());
}
}
QString KDialog::helpLinkText() const
{
Q_D(const KDialog);
return (d->mHelpLinkText.isEmpty() ? i18n("Get help...") : d->mHelpLinkText);
}
void KDialog::hideEvent(QHideEvent *event)
{
emit hidden();
if (!event->spontaneous()) {
emit finished();
}
}
void KDialog::closeEvent(QCloseEvent *event)
{
Q_D(KDialog);
KPushButton *button = this->button(d->mEscapeButton);
if (button && !isHidden()) {
button->animateClick();
if (testAttribute(Qt::WA_DeleteOnClose)) {
// Don't let QWidget::close do a deferred delete just yet, wait for the click first
d->mDeferredDelete = true;
setAttribute(Qt::WA_DeleteOnClose, false);
}
} else {
QDialog::closeEvent(event);
}
}
void KDialog::restoreDialogSize(const KConfigGroup &cfg)
{
int width, height;
int scnum = QApplication::desktop()->screenNumber(parentWidget());
QRect desk = QApplication::desktop()->screenGeometry(scnum);
width = sizeHint().width();
height = sizeHint().height();
width = cfg.readEntry(QString::fromLatin1("Width %1").arg(desk.width()), width);
height = cfg.readEntry(QString::fromLatin1("Height %1").arg(desk.height()), height);
resize(width, height);
}
void KDialog::saveDialogSize(KConfigGroup &config, KConfigGroup::WriteConfigFlags options) const
{
int scnum = QApplication::desktop()->screenNumber(parentWidget());
QRect desk = QApplication::desktop()->screenGeometry(scnum);
const QSize sizeToSave = size();
config.writeEntry(QString::fromLatin1("Width %1").arg(desk.width()), sizeToSave.width(), options);
config.writeEntry(QString::fromLatin1("Height %1").arg(desk.height()), sizeToSave.height(), options);
}
void KDialog::setAllowEmbeddingInGraphicsView(bool allowEmbedding)
{
sAllowEmbeddingInGraphicsView = allowEmbedding;
}
class KDialogQueue::Private
{
public:
Private(KDialogQueue *q): q(q), busy(false) {}
void slotShowQueuedDialog();
KDialogQueue *q;
QList< QPointer<QDialog> > queue;
bool busy;
};
KDialogQueue* KDialogQueue::self()
{
K_GLOBAL_STATIC(KDialogQueue, _self)
return _self;
}
KDialogQueue::KDialogQueue()
: d(new Private(this))
{
}
KDialogQueue::~KDialogQueue()
{
delete d;
}
// static
void KDialogQueue::queueDialog(QDialog *dialog)
{
KDialogQueue *_this = self();
_this->d->queue.append(dialog);
QTimer::singleShot(0, _this, SLOT(slotShowQueuedDialog()));
}
void KDialogQueue::Private::slotShowQueuedDialog()
{
if (busy) {
return;
}
QDialog *dialog = nullptr;
do {
if (queue.isEmpty()) {
return;
}
dialog = queue.first();
queue.pop_front();
} while(!dialog);
busy = true;
dialog->show();
KWindowSystem::raiseWindow(dialog->winId());
KWindowSystem::forceActiveWindow(dialog->winId());
dialog->exec();
busy = false;
delete dialog;
if (!queue.isEmpty()) {
QTimer::singleShot(20, q, SLOT(slotShowQueuedDialog()));
}
}
#include "moc_kdialog.cpp"
#include "moc_kdialogqueue_p.cpp"