kdelibs/kdeui/dialogs/kdialog.cpp

1101 lines
27 KiB
C++
Raw Normal View History

2014-11-13 01:04:59 +02:00
/* 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>
2014-11-13 01:04:59 +02:00
#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->setWindowTitle(KGlobal::caption()); // set appropriate initial window title for case it gets not set later
2014-11-13 01:04:59 +02:00
}
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 );
setWindowTitle( caption );
2014-11-13 01:04:59 +02:00
}
void KDialog::setCaption( const QString &caption, bool modified )
{
CaptionFlags flags = HIGCompliantCaption;
if ( modified )
{
flags |= ModifiedCaption;
}
setWindowTitle( makeStandardCaption(caption, this, flags) );
2014-11-13 01:04:59 +02:00
}
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->screenCount() ) {
2014-11-13 01:04:59 +02:00
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 "moc_kdialog.cpp"
#include "moc_kdialogqueue_p.cpp"