kdelibs/kdeui/dialogs/kdialog.cpp

1132 lines
29 KiB
C++
Raw Permalink 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>
#include <kwindowsystem.h>
2014-11-13 01:04:59 +02:00
#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);
2014-11-13 01:04:59 +02:00
dirty = true;
}
}
void KDialogPrivate::queuedLayoutUpdate()
{
if (!dirty) {
return;
}
2014-11-13 01:04:59 +02:00
dirty = false;
2014-11-13 01:04:59 +02:00
Q_Q(KDialog);
2014-11-13 01:04:59 +02:00
// 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();
}
2014-11-13 01:04:59 +02:00
delete mTopLayout;
2014-11-13 01:04:59 +02:00
if (mButtonOrientation == Qt::Horizontal) {
2014-11-13 01:04:59 +02:00
mTopLayout = new QVBoxLayout(q);
} else {
2014-11-13 01:04:59 +02:00
mTopLayout = new QHBoxLayout(q);
}
2014-11-13 01:04:59 +02:00
if (mUrlHelp) {
mTopLayout->addWidget(mUrlHelp, 0, Qt::AlignRight);
}
2014-11-13 01:04:59 +02:00
if (mMainWidget) {
mTopLayout->addWidget(mMainWidget, 10);
}
2014-11-13 01:04:59 +02:00
if (mDetailsWidget) {
mTopLayout->addWidget(mDetailsWidget);
}
2014-11-13 01:04:59 +02:00
if (mActionSeparator) {
mTopLayout->addWidget(mActionSeparator);
}
2014-11-13 01:04:59 +02:00
if (mButtonBox) {
mButtonBox->setOrientation(mButtonOrientation);
mTopLayout->addWidget(mButtonBox);
}
2014-11-13 01:04:59 +02:00
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()));
2014-11-13 01:04:59 +02:00
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())
2014-11-13 01:04:59 +02:00
{
d_ptr->init(this);
}
KDialog::KDialog(KDialogPrivate &dd, QWidget *parent, Qt::WindowFlags flags)
: QDialog(parent, sAllowEmbeddingInGraphicsView ? flags : flags | Qt::BypassGraphicsProxyWidget),
d_ptr(&dd)
2014-11-13 01:04:59 +02:00
{
d_ptr->init(this);
}
KDialog::~KDialog()
{
delete d_ptr;
}
void KDialog::setButtons(ButtonCodes buttonMask)
2014-11-13 01:04:59 +02:00
{
Q_D(KDialog);
if (d->mButtonBox) {
d->mButtonList.clear();
delete d->mButtonBox;
d->mButtonBox = 0;
}
2014-11-13 01:04:59 +02:00
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
}
2014-11-13 01:04:59 +02:00
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);
}
2014-11-13 01:04:59 +02:00
d->setupLayout();
}
void KDialog::setButtonsOrientation(Qt::Orientation orientation)
2014-11-13 01:04:59 +02:00
{
Q_D(KDialog);
if (d->mButtonOrientation != orientation) {
d->mButtonOrientation = orientation;
2014-11-13 01:04:59 +02:00
if (d->mActionSeparator) {
d->mActionSeparator->setOrientation(d->mButtonOrientation);
}
2014-11-13 01:04:59 +02:00
if (d->mButtonOrientation == Qt::Vertical) {
enableLinkedHelp(false); // 2000-06-18 Espen: No support for this yet.
}
}
2014-11-13 01:04:59 +02:00
}
void KDialog::setEscapeButton(ButtonCode id)
2014-11-13 01:04:59 +02:00
{
d_func()->mEscapeButton = id;
}
void KDialog::setDefaultButton(ButtonCode newDefaultButton)
2014-11-13 01:04:59 +02:00
{
Q_D(KDialog);
if (newDefaultButton == KDialog::None) {
newDefaultButton = KDialog::NoDefault; // #148969
}
2014-11-13 01:04:59 +02:00
const KDialog::ButtonCode oldDefault = defaultButton();
bool oldDefaultHadFocus = false;
if (oldDefault != KDialog::NoDefault) {
2014-11-13 01:04:59 +02:00
KPushButton *old = button(oldDefault);
if (old) {
oldDefaultHadFocus = (focusWidget() == old);
old->setDefault(false);
}
}
if (newDefaultButton != KDialog::NoDefault) {
2014-11-13 01:04:59 +02:00
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());
}
2014-11-13 01:04:59 +02:00
}
return d->mDefaultButton;
}
void KDialog::setMainWidget(QWidget *widget)
2014-11-13 01:04:59 +02:00
{
Q_D(KDialog);
if (d->mMainWidget == widget) {
2014-11-13 01:04:59 +02:00
return;
}
2014-11-13 01:04:59 +02:00
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));
}
2014-11-13 01:04:59 +02:00
return d->mMainWidget;
}
QSize KDialog::sizeHint() const
{
Q_D(const KDialog);
if (!d->mMinSize.isEmpty()) {
2014-11-13 01:04:59 +02:00
return d->mMinSize.expandedTo( minimumSizeHint() ) + d->mIncSize;
}
if (d->dirty) {
const_cast<KDialogPrivate*>(d)->queuedLayoutUpdate();
}
return QDialog::sizeHint() + d->mIncSize;
2014-11-13 01:04:59 +02:00
}
QSize KDialog::minimumSizeHint() const
{
Q_D(const KDialog);
if (d->dirty) {
2014-11-13 01:04:59 +02:00
const_cast<KDialogPrivate*>(d)->queuedLayoutUpdate();
}
2014-11-13 01:04:59 +02:00
return QDialog::minimumSizeHint() + d->mIncSize;
}
//
// Grab QDialogs keypresses if non-modal.
//
void KDialog::keyPressEvent(QKeyEvent *event)
2014-11-13 01:04:59 +02:00
{
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;
}
}
2014-11-13 01:04:59 +02:00
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();
2014-11-13 01:04:59 +02:00
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;
}
2014-11-13 01:04:59 +02:00
}
QDialog::keyPressEvent(event);
2014-11-13 01:04:59 +02:00
}
int KDialog::marginHint()
{
return QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin);
2014-11-13 01:04:59 +02:00
}
int KDialog::spacingHint()
{
return QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
2014-11-13 01:04:59 +02:00
}
int KDialog::groupSpacingHint()
{
return QApplication::fontMetrics().lineSpacing();
}
QString KDialog::makeStandardCaption(const QString &userCaption,
QWidget* window,
CaptionFlags flags)
2014-11-13 01:04:59 +02:00
{
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)) {
2014-11-13 01:04:59 +02:00
// 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;
}
}
2014-11-13 01:04:59 +02:00
return captionString;
2014-11-13 01:04:59 +02:00
}
void KDialog::setCaption(const QString &caption)
2014-11-13 01:04:59 +02:00
{
setWindowTitle(makeStandardCaption(caption, this));
2014-11-13 01:04:59 +02:00
}
void KDialog::setCaption(const QString &caption, bool modified)
2014-11-13 01:04:59 +02:00
{
CaptionFlags flags = HIGCompliantCaption;
if (modified) {
2014-11-13 01:04:59 +02:00
flags |= ModifiedCaption;
}
setWindowTitle(makeStandardCaption(caption, this, flags));
2014-11-13 01:04:59 +02:00
}
static QRect screenRect(QWidget *widget, int screen)
2014-11-13 01:04:59 +02:00
{
QDesktopWidget *desktop = QApplication::desktop();
KConfig gc("kdeglobals", KConfig::NoGlobals);
KConfigGroup cg(&gc, "Windows");
if (desktop->isVirtualDesktop() &&
cg.readEntry("XineramaEnabled", true) &&
cg.readEntry("XineramaPlacementEnabled", true))
{
2014-11-13 01:04:59 +02:00
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);
}
}
2014-11-13 01:04:59 +02:00
return desktop->availableGeometry(screen);
}
2014-11-13 01:04:59 +02:00
return desktop->geometry();
}
void KDialog::centerOnScreen( QWidget *widget, int screen )
{
if (!widget) {
return;
}
2014-11-13 01:04:59 +02:00
#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
}
2014-11-13 01:04:59 +02:00
#endif
const QRect rect = screenRect(widget, screen);
widget->move(
rect.center().x() - widget->width() / 2,
rect.center().y() - widget->height() / 2
);
2014-11-13 01:04:59 +02:00
}
bool KDialog::avoidArea(QWidget *widget, const QRect &area, int screen)
2014-11-13 01:04:59 +02:00
{
if (!widget) {
return false;
}
2014-11-13 01:04:59 +02:00
QRect fg = widget->frameGeometry();
if (!fg.intersects(area)) {
return true; // nothing to do.
}
2014-11-13 01:04:59 +02:00
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);
2014-11-13 01:04:59 +02:00
if (qMax(fg.top(), avoid.top()) <= qMin(fg.bottom(), avoid.bottom())) {
2014-11-13 01:04:59 +02:00
// 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;
}
}
}
2014-11-13 01:04:59 +02:00
widget->move(fg.x(), fg.y());
2014-11-13 01:04:59 +02:00
return true;
2014-11-13 01:04:59 +02:00
}
void KDialog::showButtonSeparator(bool state)
2014-11-13 01:04:59 +02:00
{
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;
}
2014-11-13 01:04:59 +02:00
d->setupLayout();
2014-11-13 01:04:59 +02:00
}
void KDialog::setInitialSize(const QSize &size)
2014-11-13 01:04:59 +02:00
{
d_func()->mMinSize = size;
adjustSize();
2014-11-13 01:04:59 +02:00
}
void KDialog::incrementInitialSize(const QSize &size)
2014-11-13 01:04:59 +02:00
{
d_func()->mIncSize = size;
adjustSize();
2014-11-13 01:04:59 +02:00
}
KPushButton* KDialog::button(ButtonCode id) const
2014-11-13 01:04:59 +02:00
{
Q_D(const KDialog);
return d->mButtonList.value(id, 0);
2014-11-13 01:04:59 +02:00
}
void KDialog::enableButton(ButtonCode id, bool state)
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
button->setEnabled(state);
}
2014-11-13 01:04:59 +02:00
}
bool KDialog::isButtonEnabled(ButtonCode id) const
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
return button->isEnabled();
}
return false;
2014-11-13 01:04:59 +02:00
}
void KDialog::enableButtonOk(bool state)
2014-11-13 01:04:59 +02:00
{
enableButton(KDialog::Ok, state);
2014-11-13 01:04:59 +02:00
}
void KDialog::enableButtonApply(bool state)
2014-11-13 01:04:59 +02:00
{
enableButton(KDialog::Apply, state);
2014-11-13 01:04:59 +02:00
}
void KDialog::enableButtonCancel(bool state)
2014-11-13 01:04:59 +02:00
{
enableButton(KDialog::Cancel, state);
2014-11-13 01:04:59 +02:00
}
void KDialog::showButton(ButtonCode id, bool state)
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
state ? button->show() : button->hide();
}
2014-11-13 01:04:59 +02:00
}
void KDialog::setButtonGuiItem(ButtonCode id, const KGuiItem &item)
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (!button) {
return;
}
button->setGuiItem(item);
2014-11-13 01:04:59 +02:00
}
void KDialog::setButtonMenu(ButtonCode id, QMenu *menu, ButtonPopupMode popupmode)
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
if (popupmode == KDialog::InstantPopup) {
button->setMenu(menu);
} else {
button->setDelayedMenu(menu);
}
}
2014-11-13 01:04:59 +02:00
}
void KDialog::setButtonText(ButtonCode id, const QString &text)
2014-11-13 01:04:59 +02:00
{
Q_D(KDialog);
if (!d->mSettingDetails && (id == KDialog::Details)) {
d->mDetailsButtonText = text;
setDetailsWidgetVisible(d->mDetailsVisible);
return;
}
2014-11-13 01:04:59 +02:00
KPushButton *button = this->button(id);
if (button) {
button->setText(text);
}
2014-11-13 01:04:59 +02:00
}
QString KDialog::buttonText(ButtonCode id) const
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
return button->text();
}
2014-11-13 01:04:59 +02:00
return QString();
}
void KDialog::setButtonIcon(ButtonCode id, const KIcon &icon)
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
button->setIcon(icon);
}
2014-11-13 01:04:59 +02:00
}
KIcon KDialog::buttonIcon(ButtonCode id) const
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
return KIcon(button->icon());
}
2014-11-13 01:04:59 +02:00
return KIcon();
}
void KDialog::setButtonToolTip( ButtonCode id, const QString &text)
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
if (text.isEmpty()) {
button->setToolTip(QString());
} else {
button->setToolTip(text);
}
}
2014-11-13 01:04:59 +02:00
}
QString KDialog::buttonToolTip(ButtonCode id) const
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
return button->toolTip();
}
2014-11-13 01:04:59 +02:00
return QString();
}
void KDialog::setButtonWhatsThis(ButtonCode id, const QString &text)
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
if (text.isEmpty()) {
button->setWhatsThis(QString());
} else {
button->setWhatsThis(text);
}
}
2014-11-13 01:04:59 +02:00
}
QString KDialog::buttonWhatsThis(ButtonCode id) const
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
return button->whatsThis();
}
2014-11-13 01:04:59 +02:00
return QString();
}
void KDialog::setButtonFocus(ButtonCode id)
2014-11-13 01:04:59 +02:00
{
KPushButton *button = this->button(id);
if (button) {
button->setFocus();
}
2014-11-13 01:04:59 +02:00
}
void KDialog::setDetailsWidget(QWidget *detailsWidget)
2014-11-13 01:04:59 +02:00
{
Q_D(KDialog);
if (d->mDetailsWidget == detailsWidget) {
return;
}
delete d->mDetailsWidget;
d->mDetailsWidget = detailsWidget;
2014-11-13 01:04:59 +02:00
if (d->mDetailsWidget->parentWidget() != this) {
d->mDetailsWidget->setParent(this);
}
2014-11-13 01:04:59 +02:00
d->mDetailsWidget->hide();
d->setupLayout();
2014-11-13 01:04:59 +02:00
if (!d->mSettingDetails) {
setDetailsWidgetVisible(d->mDetailsVisible);
}
2014-11-13 01:04:59 +02:00
}
bool KDialog::isDetailsWidgetVisible() const
{
return d_func()->mDetailsVisible;
}
void KDialog::setDetailsWidgetVisible(bool visible)
2014-11-13 01:04:59 +02:00
{
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);
}
2014-11-13 01:04:59 +02:00
d->mDetailsWidget->show();
2014-11-13 01:04:59 +02:00
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();
}
2014-11-13 01:04:59 +02:00
if (layout()) {
layout()->activate();
if (layout()->sizeConstraint() == QLayout::SetFixedSize) {
adjustSize();
}
}
2014-11-13 01:04:59 +02:00
}
d->mSettingDetails = false;
2014-11-13 01:04:59 +02:00
}
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;
}
}
2014-11-13 01:04:59 +02:00
// 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)
2014-11-13 01:04:59 +02:00
{
Q_D(KDialog);
if ((d->mUrlHelp != 0) == state) {
2014-11-13 01:04:59 +02:00
return;
}
if (state) {
if (d->mUrlHelp) {
2014-11-13 01:04:59 +02:00
return;
}
2014-11-13 01:04:59 +02:00
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()));
2014-11-13 01:04:59 +02:00
d->mUrlHelp->show();
} else {
delete d->mUrlHelp;
d->mUrlHelp = 0;
}
d->setupLayout();
}
void KDialog::setHelp(const QString &anchor, const QString &appname)
2014-11-13 01:04:59 +02:00
{
Q_D(KDialog);
d->mAnchor = anchor;
d->mHelpApp = appname;
2014-11-13 01:04:59 +02:00
}
void KDialog::setHelpLinkText(const QString &text)
2014-11-13 01:04:59 +02:00
{
Q_D(KDialog);
d->mHelpLinkText = text;
if (d->mUrlHelp) {
d->mUrlHelp->setText(helpLinkText());
}
2014-11-13 01:04:59 +02:00
}
QString KDialog::helpLinkText() const
{
Q_D(const KDialog);
return (d->mHelpLinkText.isEmpty() ? i18n("Get help...") : d->mHelpLinkText);
2014-11-13 01:04:59 +02:00
}
void KDialog::hideEvent(QHideEvent *event)
2014-11-13 01:04:59 +02:00
{
emit hidden();
if (!event->spontaneous()) {
emit finished();
}
2014-11-13 01:04:59 +02:00
}
void KDialog::closeEvent(QCloseEvent *event)
2014-11-13 01:04:59 +02:00
{
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)
2014-11-13 01:04:59 +02:00
{
int width, height;
int scnum = QApplication::desktop()->screenNumber(parentWidget());
QRect desk = QApplication::desktop()->screenGeometry(scnum);
2014-11-13 01:04:59 +02:00
width = sizeHint().width();
height = sizeHint().height();
2014-11-13 01:04:59 +02:00
width = cfg.readEntry(QString::fromLatin1("Width %1").arg(desk.width()), width);
height = cfg.readEntry(QString::fromLatin1("Height %1").arg(desk.height()), height);
2014-11-13 01:04:59 +02:00
resize(width, height);
2014-11-13 01:04:59 +02:00
}
void KDialog::saveDialogSize(KConfigGroup &config, KConfigGroup::WriteConfigFlags options) const
2014-11-13 01:04:59 +02:00
{
int scnum = QApplication::desktop()->screenNumber(parentWidget());
QRect desk = QApplication::desktop()->screenGeometry(scnum);
2014-11-13 01:04:59 +02:00
const QSize sizeToSave = size();
2014-11-13 01:04:59 +02:00
config.writeEntry(QString::fromLatin1("Width %1").arg(desk.width()), sizeToSave.width(), options);
config.writeEntry(QString::fromLatin1("Height %1").arg(desk.height()), sizeToSave.height(), options);
2014-11-13 01:04:59 +02:00
}
void KDialog::setAllowEmbeddingInGraphicsView(bool allowEmbedding)
2014-11-13 01:04:59 +02:00
{
sAllowEmbeddingInGraphicsView = allowEmbedding;
2014-11-13 01:04:59 +02:00
}
class KDialogQueue::Private
{
public:
Private(KDialogQueue *q): q(q), busy(false) {}
2014-11-13 01:04:59 +02:00
void slotShowQueuedDialog();
KDialogQueue *q;
QList< QPointer<QDialog> > queue;
bool busy;
};
KDialogQueue* KDialogQueue::self()
{
K_GLOBAL_STATIC(KDialogQueue, _self)
return _self;
2014-11-13 01:04:59 +02:00
}
KDialogQueue::KDialogQueue()
: d(new Private(this))
2014-11-13 01:04:59 +02:00
{
}
KDialogQueue::~KDialogQueue()
{
delete d;
2014-11-13 01:04:59 +02:00
}
// static
void KDialogQueue::queueDialog(QDialog *dialog)
2014-11-13 01:04:59 +02:00
{
KDialogQueue *_this = self();
_this->d->queue.append(dialog);
2014-11-13 01:04:59 +02:00
QTimer::singleShot(0, _this, SLOT(slotShowQueuedDialog()));
2014-11-13 01:04:59 +02:00
}
void KDialogQueue::Private::slotShowQueuedDialog()
{
if (busy) {
return;
}
2014-11-13 01:04:59 +02:00
QDialog *dialog = nullptr;
do {
if (queue.isEmpty()) {
return;
}
dialog = queue.first();
queue.pop_front();
} while(!dialog);
2014-11-13 01:04:59 +02:00
busy = true;
dialog->show();
KWindowSystem::raiseWindow(dialog->winId());
KWindowSystem::forceActiveWindow(dialog->winId());
dialog->exec();
busy = false;
delete dialog;
2014-11-13 01:04:59 +02:00
if (!queue.isEmpty()) {
QTimer::singleShot(20, q, SLOT(slotShowQueuedDialog()));
}
2014-11-13 01:04:59 +02:00
}
#include "moc_kdialog.cpp"
#include "moc_kdialogqueue_p.cpp"