~ubuntu-branches/debian/sid/calligraplan/sid

« back to all changes in this revision

Viewing changes to src/libs/widgets/KoDialog.cpp

  • Committer: Package Import Robot
  • Author(s): Pino Toscano
  • Date: 2018-02-01 18:20:19 UTC
  • Revision ID: package-import@ubuntu.com-20180201182019-1qo7qaim5wejm5k9
Tags: upstream-3.1.0
ImportĀ upstreamĀ versionĀ 3.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  This file is part of the KDE Libraries
 
2
 *  Copyright (C) 1998 Thomas Tanghus (tanghus@earthling.net)
 
3
 *  Additions 1999-2000 by Espen Sand (espen@kde.org)
 
4
 *                      by Holger Freyther <freyther@kde.org>
 
5
 *            2005-2009 by Olivier Goffart (ogoffart at kde.org)
 
6
 *
 
7
 *  This library is free software; you can redistribute it and/or
 
8
 *  modify it under the terms of the GNU Library General Public
 
9
 *  License as published by the Free Software Foundation; either
 
10
 *  version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 *  This library is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 *  Library General Public License for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU Library General Public License
 
18
 *  along with this library; see the file COPYING.LIB.  If not, write to
 
19
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
20
 *  Boston, MA 02110-1301, USA.
 
21
 */
 
22
 
 
23
#include "KoDialog.h"
 
24
#include "KoDialog_p.h"
 
25
 
 
26
#include <QApplication>
 
27
#include <QDesktopWidget>
 
28
#include <QDialogButtonBox>
 
29
#include <QHBoxLayout>
 
30
#include <QHideEvent>
 
31
#include <QPointer>
 
32
#include <QStyle>
 
33
#include <QTimer>
 
34
#include <QVBoxLayout>
 
35
#include <QWhatsThis>
 
36
#include <QDebug>
 
37
#include <QPushButton>
 
38
 
 
39
#include <kconfig.h>
 
40
#include <klocalizedstring.h>
 
41
 
 
42
#include <kseparator.h>
 
43
#include <kstandardguiitem.h>
 
44
#include <khelpclient.h>
 
45
#include <kurllabel.h>
 
46
#include <kwindowconfig.h>
 
47
 
 
48
void KoDialogPrivate::setupLayout()
 
49
{
 
50
    Q_Q(KoDialog);
 
51
    if (!dirty) {
 
52
        QMetaObject::invokeMethod(q, "queuedLayoutUpdate", Qt::QueuedConnection);
 
53
        dirty = true;
 
54
    }
 
55
}
 
56
 
 
57
void KoDialogPrivate::queuedLayoutUpdate()
 
58
{
 
59
    if (!dirty) {
 
60
        return;
 
61
    }
 
62
 
 
63
    dirty = false;
 
64
 
 
65
    Q_Q(KoDialog);
 
66
 
 
67
    // Don't lose the focus widget when re-creating the layout.
 
68
    // Testcase: KOrganizer's "Select Categories" dialog
 
69
    QPointer<QWidget> focusWidget = mMainWidget ? mMainWidget->focusWidget() : 0;
 
70
 
 
71
    if (q->layout() && q->layout() != mTopLayout) {
 
72
        qWarning() << q->metaObject()->className() << "created with a layout; don't do that, KoDialog takes care of it, use mainWidget or setMainWidget instead";
 
73
        delete q->layout();
 
74
    }
 
75
 
 
76
    delete mTopLayout;
 
77
 
 
78
    if (mButtonOrientation == Qt::Horizontal) {
 
79
        mTopLayout = new QVBoxLayout(q);
 
80
    } else {
 
81
        mTopLayout = new QHBoxLayout(q);
 
82
    }
 
83
 
 
84
    if (mUrlHelp) {
 
85
        mTopLayout->addWidget(mUrlHelp, 0, Qt::AlignRight);
 
86
    }
 
87
 
 
88
    if (mMainWidget) {
 
89
        mTopLayout->addWidget(mMainWidget, 10);
 
90
    }
 
91
 
 
92
    if (mDetailsWidget) {
 
93
        mTopLayout->addWidget(mDetailsWidget);
 
94
    }
 
95
 
 
96
    if (mActionSeparator) {
 
97
        mTopLayout->addWidget(mActionSeparator);
 
98
    }
 
99
 
 
100
    if (mButtonBox) {
 
101
        mButtonBox->setOrientation(mButtonOrientation);
 
102
        mTopLayout->addWidget(mButtonBox);
 
103
    }
 
104
 
 
105
    if (focusWidget) {
 
106
        focusWidget->setFocus();
 
107
    }
 
108
}
 
109
 
 
110
void KoDialogPrivate::appendButton(KoDialog::ButtonCode key, const KGuiItem &item)
 
111
{
 
112
    Q_Q(KoDialog);
 
113
 
 
114
    QDialogButtonBox::ButtonRole role = QDialogButtonBox::InvalidRole;
 
115
    switch (key) {
 
116
    case KoDialog::Help:
 
117
    case KoDialog::Details:
 
118
        role = QDialogButtonBox::HelpRole;
 
119
        break;
 
120
    case KoDialog::Default:
 
121
    case KoDialog::Reset:
 
122
        role = QDialogButtonBox::ResetRole;
 
123
        break;
 
124
    case KoDialog::Ok:
 
125
        role = QDialogButtonBox::AcceptRole;
 
126
        break;
 
127
    case KoDialog::Apply:
 
128
        role = QDialogButtonBox::ApplyRole;
 
129
        break;
 
130
    case KoDialog::Try:
 
131
    case KoDialog::Yes:
 
132
        role = QDialogButtonBox::YesRole;
 
133
        break;
 
134
    case KoDialog::Close:
 
135
    case KoDialog::Cancel:
 
136
        role = QDialogButtonBox::RejectRole;
 
137
        break;
 
138
    case KoDialog::No:
 
139
        role = QDialogButtonBox::NoRole;
 
140
        break;
 
141
    case KoDialog::User1:
 
142
    case KoDialog::User2:
 
143
    case KoDialog::User3:
 
144
        role = QDialogButtonBox::ActionRole;
 
145
        break;
 
146
    default:
 
147
        role = QDialogButtonBox::InvalidRole;
 
148
        break;
 
149
    }
 
150
 
 
151
    if (role == QDialogButtonBox::InvalidRole) {
 
152
        return;
 
153
    }
 
154
 
 
155
    QPushButton *button = new QPushButton;
 
156
    KGuiItem::assign(button, item);
 
157
    mButtonBox->addButton(button, role);
 
158
 
 
159
    mButtonList.insert(key, button);
 
160
    mButtonSignalMapper.setMapping(button, key);
 
161
 
 
162
    QObject::connect(button, SIGNAL(clicked()),
 
163
                     &mButtonSignalMapper, SLOT(map()));
 
164
 
 
165
    if (key == mDefaultButton) {
 
166
        // Now that it exists, set it as default
 
167
        q->setDefaultButton(mDefaultButton);
 
168
    }
 
169
}
 
170
 
 
171
void KoDialogPrivate::init(KoDialog *q)
 
172
{
 
173
    q_ptr = q;
 
174
 
 
175
    dirty = false;
 
176
 
 
177
    q->setButtons(KoDialog::Ok | KoDialog::Cancel);
 
178
    q->setDefaultButton(KoDialog::Ok);
 
179
 
 
180
    q->connect(&mButtonSignalMapper, SIGNAL(mapped(int)), q, SLOT(slotButtonClicked(int)));
 
181
 
 
182
    q->setPlainCaption(qApp->applicationDisplayName()); // set appropriate initial window title for case it gets not set later
 
183
}
 
184
 
 
185
void KoDialogPrivate::helpLinkClicked()
 
186
{
 
187
    q_ptr->slotButtonClicked(KoDialog::Help);
 
188
}
 
189
 
 
190
KoDialog::KoDialog(QWidget *parent, Qt::WindowFlags flags)
 
191
    : QDialog(parent, flags)
 
192
    , d_ptr(new KoDialogPrivate)
 
193
{
 
194
    d_ptr->init(this);
 
195
}
 
196
 
 
197
KoDialog::KoDialog(KoDialogPrivate &dd, QWidget *parent, Qt::WindowFlags flags)
 
198
    : QDialog(parent, flags)
 
199
    , d_ptr(&dd)
 
200
{
 
201
    d_ptr->init(this);
 
202
}
 
203
 
 
204
KoDialog::~KoDialog()
 
205
{
 
206
    delete d_ptr;
 
207
}
 
208
 
 
209
void KoDialog::setButtons(ButtonCodes buttonMask)
 
210
{
 
211
    Q_D(KoDialog);
 
212
    if (d->mButtonBox) {
 
213
        d->mButtonList.clear();
 
214
 
 
215
        delete d->mButtonBox;
 
216
        d->mButtonBox = 0;
 
217
    }
 
218
 
 
219
    if (buttonMask & Cancel) {
 
220
        buttonMask &= ~Close;
 
221
    }
 
222
 
 
223
    if (buttonMask & Apply) {
 
224
        buttonMask &= ~Try;
 
225
    }
 
226
 
 
227
    if (buttonMask & Details) {
 
228
        buttonMask &= ~Default;
 
229
    }
 
230
 
 
231
    if (buttonMask == None) {
 
232
        d->setupLayout();
 
233
        return; // When we want no button box
 
234
    }
 
235
 
 
236
    d->mEscapeButton = (buttonMask & Cancel) ? Cancel : Close;
 
237
    d->mButtonBox = new QDialogButtonBox(this);
 
238
 
 
239
    if (buttonMask & Help) {
 
240
        d->appendButton(Help, KStandardGuiItem::help());
 
241
    }
 
242
    if (buttonMask & Default) {
 
243
        d->appendButton(Default, KStandardGuiItem::defaults());
 
244
    }
 
245
    if (buttonMask & Reset) {
 
246
        d->appendButton(Reset, KStandardGuiItem::reset());
 
247
    }
 
248
    if (buttonMask & User3) {
 
249
        d->appendButton(User3, KGuiItem());
 
250
    }
 
251
    if (buttonMask & User2) {
 
252
        d->appendButton(User2, KGuiItem());
 
253
    }
 
254
    if (buttonMask & User1) {
 
255
        d->appendButton(User1, KGuiItem());
 
256
    }
 
257
    if (buttonMask & Ok) {
 
258
        d->appendButton(Ok, KStandardGuiItem::ok());
 
259
    }
 
260
    if (buttonMask & Apply) {
 
261
        d->appendButton(Apply, KStandardGuiItem::apply());
 
262
    }
 
263
    if (buttonMask & Try) {
 
264
        d->appendButton(Try, KGuiItem(i18n("&Try")));
 
265
    }
 
266
    if (buttonMask & Cancel) {
 
267
        d->appendButton(Cancel, KStandardGuiItem::cancel());
 
268
    }
 
269
    if (buttonMask & Close) {
 
270
        d->appendButton(Close, KStandardGuiItem::close());
 
271
    }
 
272
    if (buttonMask & Yes) {
 
273
        d->appendButton(Yes, KStandardGuiItem::yes());
 
274
    }
 
275
    if (buttonMask & No) {
 
276
        d->appendButton(No, KStandardGuiItem::no());
 
277
    }
 
278
    if (buttonMask & Details) {
 
279
        d->appendButton(Details, KGuiItem(QString(), "help-about"));
 
280
        setDetailsWidgetVisible(false);
 
281
    }
 
282
 
 
283
    d->setupLayout();
 
284
}
 
285
 
 
286
void KoDialog::setButtonsOrientation(Qt::Orientation orientation)
 
287
{
 
288
    Q_D(KoDialog);
 
289
    if (d->mButtonOrientation != orientation) {
 
290
        d->mButtonOrientation = orientation;
 
291
 
 
292
        if (d->mActionSeparator) {
 
293
            d->mActionSeparator->setOrientation(d->mButtonOrientation);
 
294
        }
 
295
 
 
296
        if (d->mButtonOrientation == Qt::Vertical) {
 
297
            enableLinkedHelp(false);    // 2000-06-18 Espen: No support for this yet.
 
298
        }
 
299
    }
 
300
}
 
301
 
 
302
void KoDialog::setEscapeButton(ButtonCode id)
 
303
{
 
304
    d_func()->mEscapeButton = id;
 
305
}
 
306
 
 
307
void KoDialog::setDefaultButton(ButtonCode newDefaultButton)
 
308
{
 
309
    Q_D(KoDialog);
 
310
 
 
311
    if (newDefaultButton == None) {
 
312
        newDefaultButton = NoDefault;    // #148969
 
313
    }
 
314
 
 
315
    const KoDialog::ButtonCode oldDefault = defaultButton();
 
316
 
 
317
    bool oldDefaultHadFocus = false;
 
318
 
 
319
    if (oldDefault != NoDefault) {
 
320
        QPushButton *old = button(oldDefault);
 
321
        if (old) {
 
322
            oldDefaultHadFocus = (focusWidget() == old);
 
323
            old->setDefault(false);
 
324
        }
 
325
    }
 
326
 
 
327
    if (newDefaultButton != NoDefault) {
 
328
        QPushButton *b = button(newDefaultButton);
 
329
        if (b) {
 
330
            b->setDefault(true);
 
331
            if (focusWidget() == 0 || oldDefaultHadFocus) {
 
332
                // No widget had focus yet, or the old default button had
 
333
                // -> ok to give focus to the new default button, so that it's
 
334
                // really default (Enter triggers it).
 
335
                // But we don't do this if the kdialog user gave focus to a
 
336
                // specific widget in the dialog.
 
337
                b->setFocus();
 
338
            }
 
339
        }
 
340
    }
 
341
    d->mDefaultButton = newDefaultButton;
 
342
    Q_ASSERT(defaultButton() == newDefaultButton);
 
343
}
 
344
 
 
345
KoDialog::ButtonCode KoDialog::defaultButton() const
 
346
{
 
347
    Q_D(const KoDialog);
 
348
    QHashIterator<int, QPushButton *> it(d->mButtonList);
 
349
    while (it.hasNext()) {
 
350
        it.next();
 
351
        if (it.value()->isDefault()) {
 
352
            return (ButtonCode)it.key();
 
353
        }
 
354
    }
 
355
 
 
356
    return d->mDefaultButton;
 
357
}
 
358
 
 
359
void KoDialog::setMainWidget(QWidget *widget)
 
360
{
 
361
    Q_D(KoDialog);
 
362
    if (d->mMainWidget == widget) {
 
363
        return;
 
364
    }
 
365
    d->mMainWidget = widget;
 
366
    if (d->mMainWidget && d->mMainWidget->layout()) {
 
367
        // Avoid double-margin problem
 
368
        d->mMainWidget->layout()->setMargin(0);
 
369
    }
 
370
    d->setupLayout();
 
371
}
 
372
 
 
373
QWidget *KoDialog::mainWidget()
 
374
{
 
375
    Q_D(KoDialog);
 
376
    if (!d->mMainWidget) {
 
377
        setMainWidget(new QWidget(this));
 
378
    }
 
379
    return d->mMainWidget;
 
380
}
 
381
 
 
382
QSize KoDialog::sizeHint() const
 
383
{
 
384
    Q_D(const KoDialog);
 
385
 
 
386
    if (!d->mMinSize.isEmpty()) {
 
387
        return d->mMinSize.expandedTo(minimumSizeHint()) + d->mIncSize;
 
388
    } else {
 
389
        if (d->dirty) {
 
390
            const_cast<KoDialogPrivate *>(d)->queuedLayoutUpdate();
 
391
        }
 
392
        return QDialog::sizeHint() + d->mIncSize;
 
393
    }
 
394
}
 
395
 
 
396
QSize KoDialog::minimumSizeHint() const
 
397
{
 
398
    Q_D(const KoDialog);
 
399
 
 
400
    if (d->dirty) {
 
401
        const_cast<KoDialogPrivate *>(d)->queuedLayoutUpdate();
 
402
    }
 
403
    return QDialog::minimumSizeHint() + d->mIncSize;
 
404
}
 
405
 
 
406
//
 
407
// Grab QDialogs keypresses if non-modal.
 
408
//
 
409
void KoDialog::keyPressEvent(QKeyEvent *event)
 
410
{
 
411
    Q_D(KoDialog);
 
412
    if (event->modifiers() == 0) {
 
413
        if (event->key() == Qt::Key_F1) {
 
414
            QPushButton *button = this->button(Help);
 
415
 
 
416
            if (button) {
 
417
                button->animateClick();
 
418
                event->accept();
 
419
                return;
 
420
            }
 
421
        }
 
422
 
 
423
        if (event->key() == Qt::Key_Escape) {
 
424
            QPushButton *button = this->button(d->mEscapeButton);
 
425
 
 
426
            if (button) {
 
427
                button->animateClick();
 
428
                event->accept();
 
429
                return;
 
430
            }
 
431
 
 
432
        }
 
433
    } else if (event->key() == Qt::Key_F1 && event->modifiers() == Qt::ShiftModifier) {
 
434
        QWhatsThis::enterWhatsThisMode();
 
435
        event->accept();
 
436
        return;
 
437
    } else if (event->modifiers() == Qt::ControlModifier &&
 
438
               (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)) {
 
439
        // accept the dialog when Ctrl-Return is pressed
 
440
        QPushButton *button = this->button(Ok);
 
441
 
 
442
        if (button) {
 
443
            button->animateClick();
 
444
            event->accept();
 
445
            return;
 
446
        }
 
447
    }
 
448
 
 
449
    QDialog::keyPressEvent(event);
 
450
}
 
451
 
 
452
int KoDialog::marginHint()
 
453
{
 
454
    return QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin);
 
455
}
 
456
 
 
457
int KoDialog::spacingHint()
 
458
{
 
459
    return QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
 
460
}
 
461
 
 
462
int KoDialog::groupSpacingHint()
 
463
{
 
464
    return QApplication::fontMetrics().lineSpacing();
 
465
}
 
466
 
 
467
QString KoDialog::makeStandardCaption(const QString &userCaption,
 
468
                                     QWidget *window,
 
469
                                     CaptionFlags flags)
 
470
{
 
471
    Q_UNUSED(window);
 
472
    QString caption = qApp->applicationDisplayName();
 
473
    QString captionString = userCaption.isEmpty() ? caption : userCaption;
 
474
 
 
475
    // If the document is modified, add '[modified]'.
 
476
    if (flags & ModifiedCaption) {
 
477
        captionString += QString::fromUtf8(" [") + i18n("modified") + QString::fromUtf8("]");
 
478
    }
 
479
 
 
480
    if (!userCaption.isEmpty()) {
 
481
        // Add the application name if:
 
482
        // User asked for it, it's not a duplication  and the app name (caption()) is not empty
 
483
        if (flags & AppNameCaption &&
 
484
                !caption.isEmpty() &&
 
485
                !userCaption.endsWith(caption)) {
 
486
            // TODO: check to see if this is a transient/secondary window before trying to add the app name
 
487
            //       on platforms that need this
 
488
            captionString += i18nc("Document/application separator in titlebar", " ā€“ ") + caption;
 
489
        }
 
490
    }
 
491
 
 
492
    return captionString;
 
493
}
 
494
 
 
495
void KoDialog::setCaption(const QString &_caption)
 
496
{
 
497
    const QString caption = makeStandardCaption(_caption, this);
 
498
    setPlainCaption(caption);
 
499
}
 
500
 
 
501
void KoDialog::setCaption(const QString &caption, bool modified)
 
502
{
 
503
    CaptionFlags flags = HIGCompliantCaption;
 
504
 
 
505
    // ### Qt5 TODO: port to [*], see QWidget::setWindowFilePath
 
506
    if (modified) {
 
507
        flags |= ModifiedCaption;
 
508
    }
 
509
 
 
510
    setPlainCaption(makeStandardCaption(caption, this, flags));
 
511
}
 
512
 
 
513
void KoDialog::setPlainCaption(const QString &caption)
 
514
{
 
515
    if (QWidget *win = window()) {
 
516
        win->setWindowTitle(caption);
 
517
    }
 
518
}
 
519
 
 
520
void KoDialog::resizeLayout(QWidget *widget, int margin, int spacing)   //static
 
521
{
 
522
    if (widget->layout()) {
 
523
        resizeLayout(widget->layout(), margin, spacing);
 
524
    }
 
525
 
 
526
    if (widget->children().count() > 0) {
 
527
        const QList<QObject *> list = widget->children();
 
528
        foreach (QObject *object, list) {
 
529
            if (object->isWidgetType()) {
 
530
                resizeLayout((QWidget *)object, margin, spacing);
 
531
            }
 
532
        }
 
533
    }
 
534
}
 
535
 
 
536
void KoDialog::resizeLayout(QLayout *layout, int margin, int spacing)   //static
 
537
{
 
538
    QLayoutItem *child;
 
539
    int pos = 0;
 
540
 
 
541
    while ((child = layout->itemAt(pos))) {
 
542
        if (child->layout()) {
 
543
            resizeLayout(child->layout(), margin, spacing);
 
544
        }
 
545
 
 
546
        ++pos;
 
547
    }
 
548
 
 
549
    if (layout->layout()) {
 
550
        layout->layout()->setMargin(margin);
 
551
        layout->layout()->setSpacing(spacing);
 
552
    }
 
553
}
 
554
 
 
555
static QRect screenRect(QWidget *widget, int screen)
 
556
{
 
557
    QDesktopWidget *desktop = QApplication::desktop();
 
558
    KConfig gc("kdeglobals", KConfig::NoGlobals);
 
559
    KConfigGroup cg(&gc, "Windows");
 
560
    if (desktop->isVirtualDesktop() &&
 
561
            cg.readEntry("XineramaEnabled", true) &&
 
562
            cg.readEntry("XineramaPlacementEnabled", true)) {
 
563
 
 
564
        if (screen < 0 || screen >= desktop->numScreens()) {
 
565
            if (screen == -1) {
 
566
                screen = desktop->primaryScreen();
 
567
            } else if (screen == -3) {
 
568
                screen = desktop->screenNumber(QCursor::pos());
 
569
            } else {
 
570
                screen = desktop->screenNumber(widget);
 
571
            }
 
572
        }
 
573
 
 
574
        return desktop->availableGeometry(screen);
 
575
    } else {
 
576
        return desktop->geometry();
 
577
    }
 
578
}
 
579
 
 
580
void KoDialog::centerOnScreen(QWidget *widget, int screen)
 
581
{
 
582
    if (!widget) {
 
583
        return;
 
584
    }
 
585
 
 
586
    QRect rect = screenRect(widget, screen);
 
587
 
 
588
    widget->move(rect.center().x() - widget->width() / 2,
 
589
                 rect.center().y() - widget->height() / 2);
 
590
}
 
591
 
 
592
bool KoDialog::avoidArea(QWidget *widget, const QRect &area, int screen)
 
593
{
 
594
    if (!widget) {
 
595
        return false;
 
596
    }
 
597
 
 
598
    QRect fg = widget->frameGeometry();
 
599
    if (!fg.intersects(area)) {
 
600
        return true;    // nothing to do.
 
601
    }
 
602
 
 
603
    const QRect scr = screenRect(widget, screen);
 
604
    QRect avoid(area);   // let's add some margin
 
605
    avoid.translate(-5, -5);
 
606
    avoid.setRight(avoid.right() + 10);
 
607
    avoid.setBottom(avoid.bottom() + 10);
 
608
 
 
609
    if (qMax(fg.top(), avoid.top()) <= qMin(fg.bottom(), avoid.bottom())) {
 
610
        // We need to move the widget up or down
 
611
        int spaceAbove = qMax(0, avoid.top() - scr.top());
 
612
        int spaceBelow = qMax(0, scr.bottom() - avoid.bottom());
 
613
        if (spaceAbove > spaceBelow)   // where's the biggest side?
 
614
            if (fg.height() <= spaceAbove) { // big enough?
 
615
                fg.setY(avoid.top() - fg.height());
 
616
            } else {
 
617
                return false;
 
618
            }
 
619
        else if (fg.height() <= spaceBelow) { // big enough?
 
620
            fg.setY(avoid.bottom());
 
621
        } else {
 
622
            return false;
 
623
        }
 
624
    }
 
625
 
 
626
    if (qMax(fg.left(), avoid.left()) <= qMin(fg.right(), avoid.right())) {
 
627
        // We need to move the widget left or right
 
628
        const int spaceLeft = qMax(0, avoid.left() - scr.left());
 
629
        const int spaceRight = qMax(0, scr.right() - avoid.right());
 
630
        if (spaceLeft > spaceRight)   // where's the biggest side?
 
631
            if (fg.width() <= spaceLeft) { // big enough?
 
632
                fg.setX(avoid.left() - fg.width());
 
633
            } else {
 
634
                return false;
 
635
            }
 
636
        else if (fg.width() <= spaceRight) { // big enough?
 
637
            fg.setX(avoid.right());
 
638
        } else {
 
639
            return false;
 
640
        }
 
641
    }
 
642
 
 
643
    widget->move(fg.x(), fg.y());
 
644
 
 
645
    return true;
 
646
}
 
647
 
 
648
void KoDialog::showButtonSeparator(bool state)
 
649
{
 
650
    Q_D(KoDialog);
 
651
    if ((d->mActionSeparator != 0) == state) {
 
652
        return;
 
653
    }
 
654
    if (state) {
 
655
        if (d->mActionSeparator) {
 
656
            return;
 
657
        }
 
658
 
 
659
        d->mActionSeparator = new KSeparator(this);
 
660
        d->mActionSeparator->setOrientation(d->mButtonOrientation);
 
661
    } else {
 
662
        delete d->mActionSeparator;
 
663
        d->mActionSeparator = 0;
 
664
    }
 
665
 
 
666
    d->setupLayout();
 
667
}
 
668
 
 
669
void KoDialog::setInitialSize(const QSize &size)
 
670
{
 
671
    d_func()->mMinSize = size;
 
672
    adjustSize();
 
673
}
 
674
 
 
675
void KoDialog::incrementInitialSize(const QSize &size)
 
676
{
 
677
    d_func()->mIncSize = size;
 
678
    adjustSize();
 
679
}
 
680
 
 
681
QPushButton *KoDialog::button(ButtonCode id) const
 
682
{
 
683
    Q_D(const KoDialog);
 
684
    return d->mButtonList.value(id, 0);
 
685
}
 
686
 
 
687
void KoDialog::enableButton(ButtonCode id, bool state)
 
688
{
 
689
    QPushButton *button = this->button(id);
 
690
    if (button) {
 
691
        button->setEnabled(state);
 
692
    }
 
693
}
 
694
 
 
695
bool KoDialog::isButtonEnabled(ButtonCode id) const
 
696
{
 
697
    QPushButton *button = this->button(id);
 
698
    if (button) {
 
699
        return button->isEnabled();
 
700
    }
 
701
 
 
702
    return false;
 
703
}
 
704
 
 
705
void KoDialog::enableButtonOk(bool state)
 
706
{
 
707
    enableButton(Ok, state);
 
708
}
 
709
 
 
710
void KoDialog::enableButtonApply(bool state)
 
711
{
 
712
    enableButton(Apply, state);
 
713
}
 
714
 
 
715
void KoDialog::enableButtonCancel(bool state)
 
716
{
 
717
    enableButton(Cancel, state);
 
718
}
 
719
 
 
720
void KoDialog::showButton(ButtonCode id, bool state)
 
721
{
 
722
    QPushButton *button = this->button(id);
 
723
    if (button) {
 
724
        state ? button->show() : button->hide();
 
725
    }
 
726
}
 
727
 
 
728
void KoDialog::setButtonGuiItem(ButtonCode id, const KGuiItem &item)
 
729
{
 
730
    QPushButton *button = this->button(id);
 
731
    if (!button) {
 
732
        return;
 
733
    }
 
734
 
 
735
    KGuiItem::assign(button, item);
 
736
}
 
737
 
 
738
void KoDialog::setButtonText(ButtonCode id, const QString &text)
 
739
{
 
740
    Q_D(KoDialog);
 
741
    if (!d->mSettingDetails && (id == Details)) {
 
742
        d->mDetailsButtonText = text;
 
743
        setDetailsWidgetVisible(d->mDetailsVisible);
 
744
        return;
 
745
    }
 
746
 
 
747
    QPushButton *button = this->button(id);
 
748
    if (button) {
 
749
        button->setText(text);
 
750
    }
 
751
}
 
752
 
 
753
QString KoDialog::buttonText(ButtonCode id) const
 
754
{
 
755
    QPushButton *button = this->button(id);
 
756
    if (button) {
 
757
        return button->text();
 
758
    } else {
 
759
        return QString();
 
760
    }
 
761
}
 
762
 
 
763
void KoDialog::setButtonIcon(ButtonCode id, const QIcon &icon)
 
764
{
 
765
    QPushButton *button = this->button(id);
 
766
    if (button) {
 
767
        button->setIcon(icon);
 
768
    }
 
769
}
 
770
 
 
771
QIcon KoDialog::buttonIcon(ButtonCode id) const
 
772
{
 
773
    QPushButton *button = this->button(id);
 
774
    if (button) {
 
775
        return button->icon();
 
776
    } else {
 
777
        return QIcon();
 
778
    }
 
779
}
 
780
 
 
781
void KoDialog::setButtonToolTip(ButtonCode id, const QString &text)
 
782
{
 
783
    QPushButton *button = this->button(id);
 
784
    if (button) {
 
785
        if (text.isEmpty()) {
 
786
            button->setToolTip(QString());
 
787
        } else {
 
788
            button->setToolTip(text);
 
789
        }
 
790
    }
 
791
}
 
792
 
 
793
QString KoDialog::buttonToolTip(ButtonCode id) const
 
794
{
 
795
    QPushButton *button = this->button(id);
 
796
    if (button) {
 
797
        return button->toolTip();
 
798
    } else {
 
799
        return QString();
 
800
    }
 
801
}
 
802
 
 
803
void KoDialog::setButtonWhatsThis(ButtonCode id, const QString &text)
 
804
{
 
805
    QPushButton *button = this->button(id);
 
806
    if (button) {
 
807
        if (text.isEmpty()) {
 
808
            button->setWhatsThis(QString());
 
809
        } else {
 
810
            button->setWhatsThis(text);
 
811
        }
 
812
    }
 
813
}
 
814
 
 
815
QString KoDialog::buttonWhatsThis(ButtonCode id) const
 
816
{
 
817
    QPushButton *button = this->button(id);
 
818
    if (button) {
 
819
        return button->whatsThis();
 
820
    } else {
 
821
        return QString();
 
822
    }
 
823
}
 
824
 
 
825
void KoDialog::setButtonFocus(ButtonCode id)
 
826
{
 
827
    QPushButton *button = this->button(id);
 
828
    if (button) {
 
829
        button->setFocus();
 
830
    }
 
831
}
 
832
 
 
833
void KoDialog::setDetailsWidget(QWidget *detailsWidget)
 
834
{
 
835
    Q_D(KoDialog);
 
836
    if (d->mDetailsWidget == detailsWidget) {
 
837
        return;
 
838
    }
 
839
    delete d->mDetailsWidget;
 
840
    d->mDetailsWidget = detailsWidget;
 
841
 
 
842
    if (d->mDetailsWidget->parentWidget() != this) {
 
843
        d->mDetailsWidget->setParent(this);
 
844
    }
 
845
 
 
846
    d->mDetailsWidget->hide();
 
847
    d->setupLayout();
 
848
 
 
849
    if (!d->mSettingDetails) {
 
850
        setDetailsWidgetVisible(d->mDetailsVisible);
 
851
    }
 
852
}
 
853
 
 
854
bool KoDialog::isDetailsWidgetVisible() const
 
855
{
 
856
    return d_func()->mDetailsVisible;
 
857
}
 
858
 
 
859
void KoDialog::setDetailsWidgetVisible(bool visible)
 
860
{
 
861
    Q_D(KoDialog);
 
862
    if (d->mDetailsButtonText.isEmpty()) {
 
863
        d->mDetailsButtonText = i18n("&Details");
 
864
    }
 
865
 
 
866
    d->mSettingDetails = true;
 
867
    d->mDetailsVisible = visible;
 
868
    if (d->mDetailsVisible) {
 
869
        emit aboutToShowDetails();
 
870
        setButtonText(Details, d->mDetailsButtonText + " <<");
 
871
        if (d->mDetailsWidget) {
 
872
            if (layout()) {
 
873
                layout()->setEnabled(false);
 
874
            }
 
875
 
 
876
            d->mDetailsWidget->show();
 
877
 
 
878
            adjustSize();
 
879
 
 
880
            if (layout()) {
 
881
                layout()->activate();
 
882
                layout()->setEnabled(true);
 
883
            }
 
884
        }
 
885
    } else {
 
886
        setButtonText(Details, d->mDetailsButtonText + " >>");
 
887
        if (d->mDetailsWidget) {
 
888
            d->mDetailsWidget->hide();
 
889
        }
 
890
 
 
891
        if (layout()) {
 
892
            layout()->activate();
 
893
            adjustSize();
 
894
        }
 
895
 
 
896
    }
 
897
 
 
898
    d->mSettingDetails = false;
 
899
}
 
900
 
 
901
void KoDialog::delayedDestruct()
 
902
{
 
903
    if (isVisible()) {
 
904
        hide();
 
905
    }
 
906
 
 
907
    deleteLater();
 
908
}
 
909
 
 
910
void KoDialog::slotButtonClicked(int button)
 
911
{
 
912
    Q_D(KoDialog);
 
913
    emit buttonClicked(static_cast<KoDialog::ButtonCode>(button));
 
914
 
 
915
    switch (button) {
 
916
    case Ok:
 
917
        emit okClicked();
 
918
        accept();
 
919
        break;
 
920
    case Apply:
 
921
        emit applyClicked();
 
922
        break;
 
923
    case Try:
 
924
        emit tryClicked();
 
925
        break;
 
926
    case User3:
 
927
        emit user3Clicked();
 
928
        break;
 
929
    case User2:
 
930
        emit user2Clicked();
 
931
        break;
 
932
    case User1:
 
933
        emit user1Clicked();
 
934
        break;
 
935
    case Yes:
 
936
        emit yesClicked();
 
937
        done(Yes);
 
938
        break;
 
939
    case No:
 
940
        emit noClicked();
 
941
        done(No);
 
942
        break;
 
943
    case Cancel:
 
944
        emit cancelClicked();
 
945
        reject();
 
946
        break;
 
947
    case Close:
 
948
        emit closeClicked();
 
949
        done(Close); // KDE5: call reject() instead; more QDialog-like.
 
950
        break;
 
951
    case Help:
 
952
        emit helpClicked();
 
953
        if (!d->mAnchor.isEmpty() || !d->mHelpApp.isEmpty()) {
 
954
            KHelpClient::invokeHelp(d->mAnchor, d->mHelpApp);
 
955
        }
 
956
        break;
 
957
    case Default:
 
958
        emit defaultClicked();
 
959
        break;
 
960
    case Reset:
 
961
        emit resetClicked();
 
962
        break;
 
963
    case Details:
 
964
        setDetailsWidgetVisible(!d->mDetailsVisible);
 
965
        break;
 
966
    }
 
967
 
 
968
    // If we're here from the closeEvent, and auto-delete is on, well, auto-delete now.
 
969
    if (d->mDeferredDelete) {
 
970
        d->mDeferredDelete = false;
 
971
        delayedDestruct();
 
972
    }
 
973
}
 
974
 
 
975
void KoDialog::enableLinkedHelp(bool state)
 
976
{
 
977
    Q_D(KoDialog);
 
978
    if ((d->mUrlHelp != 0) == state) {
 
979
        return;
 
980
    }
 
981
    if (state) {
 
982
        if (d->mUrlHelp) {
 
983
            return;
 
984
        }
 
985
 
 
986
        d->mUrlHelp = new KUrlLabel(this);
 
987
        d->mUrlHelp->setText(helpLinkText());
 
988
        d->mUrlHelp->setFloatEnabled(true);
 
989
        d->mUrlHelp->setUnderline(true);
 
990
        d->mUrlHelp->setMinimumHeight(fontMetrics().height() + marginHint());
 
991
        connect(d->mUrlHelp, SIGNAL(leftClickedUrl()), SLOT(helpLinkClicked()));
 
992
 
 
993
        d->mUrlHelp->show();
 
994
    } else {
 
995
        delete d->mUrlHelp;
 
996
        d->mUrlHelp = 0;
 
997
    }
 
998
 
 
999
    d->setupLayout();
 
1000
}
 
1001
 
 
1002
void KoDialog::setHelp(const QString &anchor, const QString &appname)
 
1003
{
 
1004
    Q_D(KoDialog);
 
1005
    d->mAnchor  = anchor;
 
1006
    d->mHelpApp = appname;
 
1007
}
 
1008
 
 
1009
void KoDialog::setHelpLinkText(const QString &text)
 
1010
{
 
1011
    Q_D(KoDialog);
 
1012
    d->mHelpLinkText = text;
 
1013
    if (d->mUrlHelp) {
 
1014
        d->mUrlHelp->setText(helpLinkText());
 
1015
    }
 
1016
}
 
1017
 
 
1018
QString KoDialog::helpLinkText() const
 
1019
{
 
1020
    Q_D(const KoDialog);
 
1021
    return (d->mHelpLinkText.isEmpty() ? i18n("Get help...") : d->mHelpLinkText);
 
1022
}
 
1023
 
 
1024
void KoDialog::updateGeometry()
 
1025
{
 
1026
}
 
1027
 
 
1028
void KoDialog::hideEvent(QHideEvent *event)
 
1029
{
 
1030
    emit hidden();
 
1031
 
 
1032
    if (!event->spontaneous()) {
 
1033
        emit finished();
 
1034
    }
 
1035
}
 
1036
 
 
1037
void KoDialog::closeEvent(QCloseEvent *event)
 
1038
{
 
1039
    Q_D(KoDialog);
 
1040
    QPushButton *button = this->button(d->mEscapeButton);
 
1041
    if (button && !isHidden()) {
 
1042
        button->animateClick();
 
1043
 
 
1044
        if (testAttribute(Qt::WA_DeleteOnClose)) {
 
1045
            // Don't let QWidget::close do a deferred delete just yet, wait for the click first
 
1046
            d->mDeferredDelete = true;
 
1047
            setAttribute(Qt::WA_DeleteOnClose, false);
 
1048
        }
 
1049
    } else {
 
1050
        QDialog::closeEvent(event);
 
1051
    }
 
1052
}
 
1053
 
 
1054
#include "moc_KoDialog.cpp"