kdelibs/kdeui/dialogs/kdialog.cpp
2014-11-13 01:04:59 +02:00

1112 lines
27 KiB
C++
Raw 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 <QHideEvent>
#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>
#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(240) << 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->setPlainCaption(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 & Cancel )
buttonMask &= ~Close;
if ( buttonMask & Apply )
buttonMask &= ~Try;
if ( buttonMask & Details )
buttonMask &= ~Default;
if ( buttonMask == None ) {
d->setupLayout();
return; // When we want no button box
}
d->mEscapeButton = (buttonMask & Cancel) ? Cancel : Close;
d->mButtonBox = new QDialogButtonBox( this );
if ( buttonMask & Help )
d->appendButton( Help, KStandardGuiItem::help() );
if ( buttonMask & Default )
d->appendButton( Default, KStandardGuiItem::defaults() );
if ( buttonMask & Reset )
d->appendButton( Reset, KStandardGuiItem::reset() );
if ( buttonMask & User3 )
d->appendButton( User3, KGuiItem() );
if ( buttonMask & User2 )
d->appendButton( User2, KGuiItem() );
if ( buttonMask & User1 )
d->appendButton( User1, KGuiItem() );
if ( buttonMask & Ok )
d->appendButton( Ok, KStandardGuiItem::ok() );
if ( buttonMask & Apply )
d->appendButton( Apply, KStandardGuiItem::apply() );
if ( buttonMask & Try )
d->appendButton( Try, KGuiItem(i18n( "&Try" )) );
if ( buttonMask & Cancel )
d->appendButton( Cancel, KStandardGuiItem::cancel() );
if ( buttonMask & Close )
d->appendButton( Close, KStandardGuiItem::close() );
if ( buttonMask & Yes )
d->appendButton( Yes, KStandardGuiItem::yes() );
if ( buttonMask & No )
d->appendButton( No, KStandardGuiItem::no() );
if ( buttonMask & Details ) {
d->appendButton( 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 == None)
newDefaultButton = NoDefault; // #148969
const KDialog::ButtonCode oldDefault = defaultButton();
bool oldDefaultHadFocus = false;
if (oldDefault != NoDefault) {
KPushButton *old = button(oldDefault);
if (old) {
oldDefaultHadFocus = (focusWidget() == old);
old->setDefault(false);
}
}
if (newDefaultButton != 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 (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;
else {
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( 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( 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 & 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 )
{
const QString caption = makeStandardCaption( _caption, this );
setPlainCaption( caption );
}
void KDialog::setCaption( const QString &caption, bool modified )
{
CaptionFlags flags = HIGCompliantCaption;
if ( modified )
{
flags |= ModifiedCaption;
}
setPlainCaption( makeStandardCaption(caption, this, flags) );
}
void KDialog::setPlainCaption( const QString &caption )
{
if (QWidget *win = window()) {
win->setWindowTitle( caption );
#ifdef Q_WS_X11
NETWinInfo info( QX11Info::display(), win->winId(), QX11Info::appRootWindow(), 0 );
info.setName( caption.toUtf8().constData() );
#endif
}
}
void KDialog::resizeLayout( QWidget *widget, int margin, int spacing ) //static
{
if ( widget->layout() )
resizeLayout( widget->layout(), margin, spacing );
if ( widget->children().count() > 0 ) {
const QList<QObject*> list = widget->children();
foreach ( QObject *object, list ) {
if ( object->isWidgetType() )
resizeLayout( (QWidget*)object, margin, spacing );
}
}
}
void KDialog::resizeLayout( QLayout *layout, int margin, int spacing ) //static
{
QLayoutItem *child;
int pos = 0;
while ( (child = layout->itemAt( pos ) ) ) {
if ( child->layout() )
resizeLayout( child->layout(), margin, spacing );
++pos;
}
if ( layout->layout() ) {
layout->layout()->setMargin( margin );
layout->layout()->setSpacing( spacing );
}
}
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->numScreens() ) {
if ( screen == -1 )
screen = desktop->primaryScreen();
else if ( screen == -3 )
screen = desktop->screenNumber( QCursor::pos() );
else
screen = desktop->screenNumber( widget );
}
return desktop->availableGeometry( screen );
} else
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
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( Ok, state );
}
void KDialog::enableButtonApply( bool state )
{
enableButton( Apply, state );
}
void KDialog::enableButtonCancel( bool state )
{
enableButton( 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==InstantPopup)
button->setMenu( menu );
else
button->setDelayedMenu(menu);
}
}
void KDialog::setButtonText( ButtonCode id, const QString &text )
{
Q_D(KDialog);
if ( !d->mSettingDetails && (id == 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();
else
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());
else
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();
else
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();
else
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( Details, d->mDetailsButtonText + " <<" );
if ( d->mDetailsWidget ) {
if ( layout() )
layout()->setEnabled( false );
d->mDetailsWidget->show();
adjustSize();
if ( layout() ) {
layout()->activate();
layout()->setEnabled( true );
}
}
} else {
setButtonText( Details, d->mDetailsButtonText + " >>" );
if ( d->mDetailsWidget )
d->mDetailsWidget->hide();
if ( layout() ) {
layout()->activate();
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 Ok:
emit okClicked();
accept();
break;
case Apply:
emit applyClicked();
break;
case Try:
emit tryClicked();
break;
case User3:
emit user3Clicked();
break;
case User2:
emit user2Clicked();
break;
case User1:
emit user1Clicked();
break;
case Yes:
emit yesClicked();
done( Yes );
break;
case No:
emit noClicked();
done( No );
break;
case Cancel:
emit cancelClicked();
reject();
break;
case Close:
emit closeClicked();
done(Close); // KDE5: call reject() instead; more QDialog-like.
break;
case Help:
emit helpClicked();
if ( !d->mAnchor.isEmpty() || !d->mHelpApp.isEmpty() )
KToolInvocation::invokeHelp( d->mAnchor, d->mHelpApp );
break;
case Default:
emit defaultClicked();
break;
case Reset:
emit resetClicked();
break;
case 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::updateGeometry()
{
}
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) {}
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) )
{
d->busy = false;
}
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;
do {
if ( queue.isEmpty() )
return;
dialog = queue.first();
queue.pop_front();
} while( !dialog );
busy = true;
dialog->exec();
busy = false;
delete dialog;
if ( !queue.isEmpty() )
QTimer::singleShot( 20, q, SLOT(slotShowQueuedDialog()) );
}
#include "kdialog.moc"
#include "kdialogqueue_p.moc"