mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00
1112 lines
27 KiB
C++
1112 lines
27 KiB
C++
/* 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"
|