380
415
void MessageWin::initView()
382
bool reminder = (!mErrorWindow && (mAlarmType & KAAlarm::REMINDER_ALARM));
383
int leading = fontMetrics().leading();
384
setCaption((mAlarmType & KAAlarm::REMINDER_ALARM) ? i18nc("@title:window", "Reminder") : i18nc("@title:window", "Message"));
385
QWidget* topWidget = new QWidget(this);
386
setCentralWidget(topWidget);
387
QVBoxLayout* topLayout = new QVBoxLayout(topWidget);
388
topLayout->setMargin(KDialog::marginHint());
389
topLayout->setSpacing(KDialog::spacingHint());
391
QPalette labelPalette = palette();
392
labelPalette.setColor(backgroundRole(), labelPalette.color(QPalette::Window));
394
// Show the alarm date/time, together with an advance reminder text where appropriate
395
// Alarm date/time: display time zone if not local time zone.
396
mTimeLabel = new QLabel(topWidget);
397
mTimeLabel->setText(dateTimeToDisplay());
398
mTimeLabel->setFrameStyle(QFrame::Box | QFrame::Raised);
399
mTimeLabel->setPalette(labelPalette);
400
mTimeLabel->setAutoFillBackground(true);
401
topLayout->addWidget(mTimeLabel, 0, Qt::AlignHCenter);
402
mTimeLabel->setWhatsThis(i18nc("@info:whatsthis", "The scheduled date/time for the message (as opposed to the actual time of display)."));
404
if (mDateTime.isValid())
409
QString s = i18nc("@info", "Reminder");
410
QRegExp re("^(<[^>]+>)*");
412
s.insert(re.matchedLength(), mTimeLabel->text() + "<br/>");
413
mTimeLabel->setText(s);
414
mTimeLabel->setAlignment(Qt::AlignHCenter);
422
// It's a normal alarm message window
425
case KAEventData::FILE:
427
// Display the file name
428
KSqueezedTextLabel* label = new KSqueezedTextLabel(mMessage, topWidget);
429
label->setFrameStyle(QFrame::Box | QFrame::Raised);
430
label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
431
label->setPalette(labelPalette);
432
label->setAutoFillBackground(true);
433
label->setWhatsThis(i18nc("@info:whatsthis", "The file whose contents are displayed below"));
434
topLayout->addWidget(label, 0, Qt::AlignHCenter);
436
// Display contents of file
441
if (KIO::NetAccess::download(url, tmpFile, MainWindow::mainMainWindow()))
443
QFile qfile(tmpFile);
444
QFileInfo info(qfile);
445
if (!(dir = info.isDir()))
448
KTextBrowser* view = new KTextBrowser(topWidget);
449
view->setFrameStyle(QFrame::NoFrame);
450
view->setWordWrapMode(QTextOption::NoWrap);
451
QPalette pal = view->viewport()->palette();
452
pal.setColor(view->viewport()->backgroundRole(), mBgColour);
453
view->viewport()->setPalette(pal);
454
view->setTextColor(mFgColour);
455
view->setCurrentFont(mFont);
456
KMimeType::Ptr mime = KMimeType::findByUrl(url);
457
if (mime->is("application/octet-stream"))
458
mime = KMimeType::findByFileContent(tmpFile);
459
switch (KAlarm::fileType(mime))
462
view->setHtml("<img source=\"" + tmpFile + "\">");
464
case KAlarm::TextFormatted:
465
view->QTextBrowser::setSource(tmpFile); //krazy:exclude=qclasses
469
// Assume a plain text file
470
if (qfile.open(QIODevice::ReadOnly))
472
QTextStream str(&qfile);
474
view->setPlainText(str.readAll());
480
view->setMinimumSize(view->sizeHint());
481
topLayout->addWidget(view);
483
// Set the default size to 20 lines square.
484
// Note that after the first file has been displayed, this size
485
// is overridden by the user-set default stored in the config file.
486
// So there is no need to calculate an accurate size.
487
int h = 20*view->fontMetrics().lineSpacing() + 2*view->frameWidth();
488
view->resize(QSize(h, h).expandedTo(view->sizeHint()));
489
view->setWhatsThis(i18nc("@info:whatsthis", "The contents of the file to be displayed"));
491
KIO::NetAccess::removeTempFile(tmpFile);
495
// File couldn't be opened
496
bool exists = KIO::NetAccess::exists(url, KIO::NetAccess::SourceSide, MainWindow::mainMainWindow());
497
mErrorMsgs += dir ? i18nc("@info", "File is a folder") : exists ? i18nc("@info", "Failed to open file") : i18nc("@info", "File not found");
501
case KAEventData::MESSAGE:
504
// Using MessageText instead of QLabel allows scrolling and mouse copying
505
MessageText* text = new MessageText(topWidget);
506
text->setAutoFillBackground(true);
507
text->setBackgroundColour(mBgColour);
508
text->setTextColor(mFgColour);
509
text->setCurrentFont(mFont);
510
text->insertPlainText(mMessage);
511
int lineSpacing = text->fontMetrics().lineSpacing();
512
QSize s = text->sizeHint();
514
text->setMaximumHeight(h + text->scrollBarHeight());
515
text->setMinimumHeight(qMin(h, lineSpacing*4));
516
text->setMaximumWidth(s.width() + text->scrollBarWidth());
517
text->setWhatsThis(i18nc("@info:whatsthis", "The alarm message"));
518
int vspace = lineSpacing/2;
519
int hspace = lineSpacing - KDialog::marginHint();
520
topLayout->addSpacing(vspace);
521
topLayout->addStretch();
522
// Don't include any horizontal margins if message is 2/3 screen width
523
if (text->sizeHint().width() >= KAlarm::desktopWorkArea(mScreenNumber).width()*2/3)
524
topLayout->addWidget(text, 1, Qt::AlignHCenter);
527
QHBoxLayout* layout = new QHBoxLayout();
528
layout->addSpacing(hspace);
529
layout->addWidget(text, 1, Qt::AlignHCenter);
530
layout->addSpacing(hspace);
531
topLayout->addLayout(layout);
534
topLayout->addStretch();
537
case KAEventData::COMMAND:
539
mCommandText = new MessageText(topWidget);
540
mCommandText->setBackgroundColour(mBgColour);
541
mCommandText->setTextColor(mFgColour);
542
mCommandText->setCurrentFont(mFont);
543
topLayout->addWidget(mCommandText);
544
mCommandText->setWhatsThis(i18nc("@info:whatsthis", "The output of the alarm's command"));
545
theApp()->execCommandAlarm(mEvent, mEvent.alarm(mAlarmType), this, SLOT(readProcessOutput(ShellProcess*)));
548
case KAEventData::EMAIL:
555
// Reminder: show remaining time until the actual alarm
556
mRemainingText = new QLabel(topWidget);
557
mRemainingText->setFrameStyle(QFrame::Box | QFrame::Raised);
558
mRemainingText->setMargin(leading);
559
mRemainingText->setPalette(labelPalette);
560
mRemainingText->setAutoFillBackground(true);
561
if (mDateTime.isDateOnly() || KDateTime::currentLocalDate().daysTo(mDateTime.date()) > 0)
563
setRemainingTextDay();
564
MidnightTimer::connect(this, SLOT(setRemainingTextDay())); // update every day
568
setRemainingTextMinute();
569
MinuteTimer::connect(this, SLOT(setRemainingTextMinute())); // update every minute
571
topLayout->addWidget(mRemainingText, 0, Qt::AlignHCenter);
572
topLayout->addSpacing(KDialog::spacingHint());
573
topLayout->addStretch();
578
// It's an error message
581
case KAEventData::EMAIL:
583
// Display the email addresses and subject.
584
QFrame* frame = new QFrame(topWidget);
585
frame->setFrameStyle(QFrame::Box | QFrame::Raised);
586
frame->setWhatsThis(i18nc("@info:whatsthis", "The email to send"));
587
topLayout->addWidget(frame, 0, Qt::AlignHCenter);
588
QGridLayout* grid = new QGridLayout(frame);
589
grid->setMargin(KDialog::marginHint());
590
grid->setSpacing(KDialog::spacingHint());
592
QLabel* label = new QLabel(i18nc("@info Email addressee", "To:"), frame);
593
label->setFixedSize(label->sizeHint());
594
grid->addWidget(label, 0, 0, Qt::AlignLeft);
595
label = new QLabel(mEvent.emailAddresses("\n"), frame);
596
label->setFixedSize(label->sizeHint());
597
grid->addWidget(label, 0, 1, Qt::AlignLeft);
599
label = new QLabel(i18nc("@info Email subject", "Subject:"), frame);
600
label->setFixedSize(label->sizeHint());
601
grid->addWidget(label, 1, 0, Qt::AlignLeft);
602
label = new QLabel(mEvent.emailSubject(), frame);
603
label->setFixedSize(label->sizeHint());
604
grid->addWidget(label, 1, 1, Qt::AlignLeft);
607
case KAEventData::COMMAND:
608
case KAEventData::FILE:
609
case KAEventData::MESSAGE:
611
// Just display the error message strings
616
if (!mErrorMsgs.count())
618
topWidget->setAutoFillBackground(true);
619
QPalette palette = topWidget->palette();
620
palette.setColor(topWidget->backgroundRole(), mBgColour);
621
topWidget->setPalette(palette);
625
setCaption(i18nc("@title:window", "Error"));
626
QHBoxLayout* layout = new QHBoxLayout();
627
layout->setMargin(2*KDialog::marginHint());
628
layout->addStretch();
629
topLayout->addLayout(layout);
630
QLabel* label = new QLabel(topWidget);
631
label->setPixmap(DesktopIcon("dialog-error"));
632
label->setFixedSize(label->sizeHint());
633
layout->addWidget(label, 0, Qt::AlignRight);
634
QVBoxLayout* vlayout = new QVBoxLayout();
635
layout->addLayout(vlayout);
636
for (QStringList::Iterator it = mErrorMsgs.begin(); it != mErrorMsgs.end(); ++it)
638
label = new QLabel(*it, topWidget);
639
label->setFixedSize(label->sizeHint());
640
vlayout->addWidget(label, 0, Qt::AlignLeft);
642
layout->addStretch();
643
if (!mDontShowAgain.isEmpty())
645
mDontShowAgainCheck = new QCheckBox(i18nc("@option:check", "Do not display this error message again for this alarm"), topWidget);
646
mDontShowAgainCheck->setFixedSize(mDontShowAgainCheck->sizeHint());
647
topLayout->addWidget(mDontShowAgainCheck, 0, Qt::AlignLeft);
651
QGridLayout* grid = new QGridLayout();
652
grid->setColumnStretch(0, 1); // keep the buttons right-adjusted in the window
653
topLayout->addLayout(grid);
657
mOkButton = new PushButton(KStandardGuiItem::close(), topWidget);
658
// Prevent accidental acknowledgement of the message if the user is typing when the window appears
659
mOkButton->clearFocus();
660
mOkButton->setFocusPolicy(Qt::ClickFocus); // don't allow keyboard selection
661
mOkButton->setFixedSize(mOkButton->sizeHint());
662
connect(mOkButton, SIGNAL(clicked()), SLOT(slotOk()));
663
grid->addWidget(mOkButton, 0, gridIndex++, Qt::AlignHCenter);
664
mOkButton->setWhatsThis(i18nc("@info:whatsthis", "Acknowledge the alarm"));
669
mEditButton = new PushButton(i18nc("@action:button", "&Edit..."), topWidget);
670
mEditButton->setFocusPolicy(Qt::ClickFocus); // don't allow keyboard selection
671
mEditButton->setFixedSize(mEditButton->sizeHint());
672
connect(mEditButton, SIGNAL(clicked()), SLOT(slotEdit()));
673
grid->addWidget(mEditButton, 0, gridIndex++, Qt::AlignHCenter);
674
mEditButton->setWhatsThis(i18nc("@info:whatsthis", "Edit the alarm."));
678
mDeferButton = new PushButton(i18nc("@action:button", "&Defer..."), topWidget);
679
mDeferButton->setFocusPolicy(Qt::ClickFocus); // don't allow keyboard selection
680
mDeferButton->setFixedSize(mDeferButton->sizeHint());
681
connect(mDeferButton, SIGNAL(clicked()), SLOT(slotDefer()));
682
grid->addWidget(mDeferButton, 0, gridIndex++, Qt::AlignHCenter);
683
mDeferButton->setWhatsThis(i18nc("@info:whatsthis", "<para>Defer the alarm until later.</para>"
684
"<para>You will be prompted to specify when the alarm should be redisplayed.</para>"));
687
mDeferButton->hide();
689
setDeferralLimit(mEvent); // ensure that button is disabled when alarm can't be deferred any more
691
if (!mAudioFile.isEmpty() && (mVolume || mFadeVolume > 0))
693
// Silence button to stop sound repetition
694
QPixmap pixmap = MainBarIcon("media-playback-stop");
695
mSilenceButton = new PushButton(topWidget);
696
mSilenceButton->setIcon(KIcon(pixmap));
697
grid->addWidget(mSilenceButton, 0, gridIndex++, Qt::AlignHCenter);
698
mSilenceButton->setToolTip(i18nc("@info:tooltip", "Stop sound"));
699
mSilenceButton->setWhatsThis(i18nc("@info:whatsthis", "Stop playing the sound"));
700
// To avoid getting in a mess, disable the button until sound playing has been set up
701
mSilenceButton->setEnabled(false);
704
KIconLoader iconLoader;
705
if (mKMailSerialNumber)
708
QPixmap pixmap = iconLoader.loadIcon(QLatin1String("internet-mail"), KIconLoader::MainToolbar);
709
mKMailButton = new PushButton(topWidget);
710
mKMailButton->setIcon(KIcon(pixmap));
711
connect(mKMailButton, SIGNAL(clicked()), SLOT(slotShowKMailMessage()));
712
grid->addWidget(mKMailButton, 0, gridIndex++, Qt::AlignHCenter);
713
mKMailButton->setToolTip(i18nc("@info:tooltip Locate this email in KMail", "Locate in <application>KMail</application>"));
714
mKMailButton->setWhatsThis(i18nc("@info:whatsthis", "Locate and highlight this email in <application>KMail</application>"));
718
QPixmap pixmap = iconLoader.loadIcon(KGlobal::mainComponent().aboutData()->appName(), KIconLoader::MainToolbar);
719
mKAlarmButton = new PushButton(topWidget);
720
mKAlarmButton->setIcon(KIcon(pixmap));
721
connect(mKAlarmButton, SIGNAL(clicked()), SLOT(displayMainWindow()));
722
grid->addWidget(mKAlarmButton, 0, gridIndex++, Qt::AlignHCenter);
723
mKAlarmButton->setToolTip(i18nc("@info:tooltip", "Activate <application>KAlarm</application>"));
724
mKAlarmButton->setWhatsThis(i18nc("@info:whatsthis", "Activate <application>KAlarm</application>"));
726
int butsize = mKAlarmButton->sizeHint().height();
728
butsize = qMax(butsize, mSilenceButton->sizeHint().height());
730
butsize = qMax(butsize, mKMailButton->sizeHint().height());
731
mKAlarmButton->setFixedSize(butsize, butsize);
733
mSilenceButton->setFixedSize(butsize, butsize);
735
mKMailButton->setFixedSize(butsize, butsize);
737
// Disable all buttons initially, to prevent accidental clicking on if they happen to be
738
// under the mouse just as the window appears.
739
mOkButton->setEnabled(false);
740
if (mDeferButton->isVisible())
741
mDeferButton->setEnabled(false);
743
mEditButton->setEnabled(false);
745
mKMailButton->setEnabled(false);
746
mKAlarmButton->setEnabled(false);
748
topLayout->activate();
749
setMinimumSize(QSize(grid->sizeHint().width() + 2*KDialog::marginHint(), sizeHint().height()));
750
bool modal = !(windowFlags() & Qt::X11BypassWindowManagerHint);
751
unsigned long wstate = (modal ? NET::Modal : 0) | NET::Sticky | NET::StaysOnTop;
753
KWindowSystem::setState(winid, wstate);
754
KWindowSystem::setOnAllDesktops(winid, true);
756
mInitialised = true; // the window's widgets have been created
417
bool reminder = (!mErrorWindow && (mAlarmType & KAAlarm::REMINDER_ALARM));
418
int leading = fontMetrics().leading();
419
setCaption((mAlarmType & KAAlarm::REMINDER_ALARM) ? i18nc("@title:window", "Reminder") : i18nc("@title:window", "Message"));
420
QWidget* topWidget = new QWidget(this);
421
setCentralWidget(topWidget);
422
QVBoxLayout* topLayout = new QVBoxLayout(topWidget);
423
topLayout->setMargin(KDialog::marginHint());
424
topLayout->setSpacing(KDialog::spacingHint());
426
QPalette labelPalette = palette();
427
labelPalette.setColor(backgroundRole(), labelPalette.color(QPalette::Window));
429
// Show the alarm date/time, together with a reminder text where appropriate.
430
// Alarm date/time: display time zone if not local time zone.
431
mTimeLabel = new QLabel(topWidget);
432
mTimeLabel->setText(dateTimeToDisplay());
433
mTimeLabel->setFrameStyle(QFrame::StyledPanel);
434
mTimeLabel->setPalette(labelPalette);
435
mTimeLabel->setAutoFillBackground(true);
436
topLayout->addWidget(mTimeLabel, 0, Qt::AlignHCenter);
437
mTimeLabel->setWhatsThis(i18nc("@info:whatsthis", "The scheduled date/time for the message (as opposed to the actual time of display)."));
439
if (mDateTime.isValid())
444
QString s = i18nc("@info", "Reminder");
445
QRegExp re("^(<[^>]+>)*");
447
s.insert(re.matchedLength(), mTimeLabel->text() + "<br/>");
448
mTimeLabel->setText(s);
449
mTimeLabel->setAlignment(Qt::AlignHCenter);
457
// It's a normal alarm message window
462
// Display the file name
463
KSqueezedTextLabel* label = new KSqueezedTextLabel(mMessage, topWidget);
464
label->setFrameStyle(QFrame::StyledPanel);
465
label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
466
label->setPalette(labelPalette);
467
label->setAutoFillBackground(true);
468
label->setWhatsThis(i18nc("@info:whatsthis", "The file whose contents are displayed below"));
469
topLayout->addWidget(label, 0, Qt::AlignHCenter);
471
// Display contents of file
476
if (KIO::NetAccess::download(url, tmpFile, MainWindow::mainMainWindow()))
478
QFile qfile(tmpFile);
479
QFileInfo info(qfile);
480
if (!(dir = info.isDir()))
483
KTextBrowser* view = new KTextBrowser(topWidget);
484
view->setFrameStyle(QFrame::NoFrame);
485
view->setWordWrapMode(QTextOption::NoWrap);
486
QPalette pal = view->viewport()->palette();
487
pal.setColor(view->viewport()->backgroundRole(), mBgColour);
488
view->viewport()->setPalette(pal);
489
view->setTextColor(mFgColour);
490
view->setCurrentFont(mFont);
491
KMimeType::Ptr mime = KMimeType::findByUrl(url);
492
if (mime->is("application/octet-stream"))
493
mime = KMimeType::findByFileContent(tmpFile);
494
switch (KAlarm::fileType(mime))
497
view->setHtml("<img source=\"" + tmpFile + "\">");
499
case KAlarm::TextFormatted:
500
view->QTextBrowser::setSource(tmpFile); //krazy:exclude=qclasses
504
// Assume a plain text file
505
if (qfile.open(QIODevice::ReadOnly))
507
QTextStream str(&qfile);
509
view->setPlainText(str.readAll());
515
view->setMinimumSize(view->sizeHint());
516
topLayout->addWidget(view);
518
// Set the default size to 20 lines square.
519
// Note that after the first file has been displayed, this size
520
// is overridden by the user-set default stored in the config file.
521
// So there is no need to calculate an accurate size.
522
int h = 20*view->fontMetrics().lineSpacing() + 2*view->frameWidth();
523
view->resize(QSize(h, h).expandedTo(view->sizeHint()));
524
view->setWhatsThis(i18nc("@info:whatsthis", "The contents of the file to be displayed"));
526
KIO::NetAccess::removeTempFile(tmpFile);
530
// File couldn't be opened
531
bool exists = KIO::NetAccess::exists(url, KIO::NetAccess::SourceSide, MainWindow::mainMainWindow());
532
mErrorMsgs += dir ? i18nc("@info", "File is a folder") : exists ? i18nc("@info", "Failed to open file") : i18nc("@info", "File not found");
536
case KAEvent::MESSAGE:
539
// Using MessageText instead of QLabel allows scrolling and mouse copying
540
MessageText* text = new MessageText(topWidget);
541
text->setAutoFillBackground(true);
542
text->setBackgroundColour(mBgColour);
543
text->setTextColor(mFgColour);
544
text->setCurrentFont(mFont);
545
text->insertPlainText(mMessage);
546
int lineSpacing = text->fontMetrics().lineSpacing();
547
QSize s = text->sizeHint();
549
text->setMaximumHeight(h + text->scrollBarHeight());
550
text->setMinimumHeight(qMin(h, lineSpacing*4));
551
text->setMaximumWidth(s.width() + text->scrollBarWidth());
552
text->setWhatsThis(i18nc("@info:whatsthis", "The alarm message"));
553
int vspace = lineSpacing/2;
554
int hspace = lineSpacing - KDialog::marginHint();
555
topLayout->addSpacing(vspace);
556
topLayout->addStretch();
557
// Don't include any horizontal margins if message is 2/3 screen width
558
if (text->sizeHint().width() >= KAlarm::desktopWorkArea(mScreenNumber).width()*2/3)
559
topLayout->addWidget(text, 1, Qt::AlignHCenter);
562
QHBoxLayout* layout = new QHBoxLayout();
563
layout->addSpacing(hspace);
564
layout->addWidget(text, 1, Qt::AlignHCenter);
565
layout->addSpacing(hspace);
566
topLayout->addLayout(layout);
569
topLayout->addStretch();
572
case KAEvent::COMMAND:
574
mCommandText = new MessageText(topWidget);
575
mCommandText->setBackgroundColour(mBgColour);
576
mCommandText->setTextColor(mFgColour);
577
mCommandText->setCurrentFont(mFont);
578
topLayout->addWidget(mCommandText);
579
mCommandText->setWhatsThis(i18nc("@info:whatsthis", "The output of the alarm's command"));
580
theApp()->execCommandAlarm(mEvent, mEvent.alarm(mAlarmType), this, SLOT(readProcessOutput(ShellProcess*)));
588
if (reminder && mEvent.reminderMinutes() > 0)
590
// Advance reminder: show remaining time until the actual alarm
591
mRemainingText = new QLabel(topWidget);
592
mRemainingText->setFrameStyle(QFrame::Box | QFrame::Raised);
593
mRemainingText->setMargin(leading);
594
mRemainingText->setPalette(labelPalette);
595
mRemainingText->setAutoFillBackground(true);
596
if (mDateTime.isDateOnly() || KDateTime::currentLocalDate().daysTo(mDateTime.date()) > 0)
598
setRemainingTextDay();
599
MidnightTimer::connect(this, SLOT(setRemainingTextDay())); // update every day
603
setRemainingTextMinute();
604
MinuteTimer::connect(this, SLOT(setRemainingTextMinute())); // update every minute
606
topLayout->addWidget(mRemainingText, 0, Qt::AlignHCenter);
607
topLayout->addSpacing(KDialog::spacingHint());
608
topLayout->addStretch();
613
// It's an error message
618
// Display the email addresses and subject.
619
QFrame* frame = new QFrame(topWidget);
620
frame->setFrameStyle(QFrame::Box | QFrame::Raised);
621
frame->setWhatsThis(i18nc("@info:whatsthis", "The email to send"));
622
topLayout->addWidget(frame, 0, Qt::AlignHCenter);
623
QGridLayout* grid = new QGridLayout(frame);
624
grid->setMargin(KDialog::marginHint());
625
grid->setSpacing(KDialog::spacingHint());
627
QLabel* label = new QLabel(i18nc("@info Email addressee", "To:"), frame);
628
label->setFixedSize(label->sizeHint());
629
grid->addWidget(label, 0, 0, Qt::AlignLeft);
630
label = new QLabel(mEvent.emailAddresses("\n"), frame);
631
label->setFixedSize(label->sizeHint());
632
grid->addWidget(label, 0, 1, Qt::AlignLeft);
634
label = new QLabel(i18nc("@info Email subject", "Subject:"), frame);
635
label->setFixedSize(label->sizeHint());
636
grid->addWidget(label, 1, 0, Qt::AlignLeft);
637
label = new QLabel(mEvent.emailSubject(), frame);
638
label->setFixedSize(label->sizeHint());
639
grid->addWidget(label, 1, 1, Qt::AlignLeft);
642
case KAEvent::COMMAND:
644
case KAEvent::MESSAGE:
646
// Just display the error message strings
651
if (!mErrorMsgs.count())
653
topWidget->setAutoFillBackground(true);
654
QPalette palette = topWidget->palette();
655
palette.setColor(topWidget->backgroundRole(), mBgColour);
656
topWidget->setPalette(palette);
660
setCaption(i18nc("@title:window", "Error"));
661
QHBoxLayout* layout = new QHBoxLayout();
662
layout->setMargin(2*KDialog::marginHint());
663
layout->addStretch();
664
topLayout->addLayout(layout);
665
QLabel* label = new QLabel(topWidget);
666
label->setPixmap(DesktopIcon("dialog-error"));
667
label->setFixedSize(label->sizeHint());
668
layout->addWidget(label, 0, Qt::AlignRight);
669
QVBoxLayout* vlayout = new QVBoxLayout();
670
layout->addLayout(vlayout);
671
for (QStringList::Iterator it = mErrorMsgs.begin(); it != mErrorMsgs.end(); ++it)
673
label = new QLabel(*it, topWidget);
674
label->setFixedSize(label->sizeHint());
675
vlayout->addWidget(label, 0, Qt::AlignLeft);
677
layout->addStretch();
678
if (!mDontShowAgain.isEmpty())
680
mDontShowAgainCheck = new QCheckBox(i18nc("@option:check", "Do not display this error message again for this alarm"), topWidget);
681
mDontShowAgainCheck->setFixedSize(mDontShowAgainCheck->sizeHint());
682
topLayout->addWidget(mDontShowAgainCheck, 0, Qt::AlignLeft);
686
QGridLayout* grid = new QGridLayout();
687
grid->setColumnStretch(0, 1); // keep the buttons right-adjusted in the window
688
topLayout->addLayout(grid);
692
mOkButton = new PushButton(KStandardGuiItem::close(), topWidget);
693
// Prevent accidental acknowledgement of the message if the user is typing when the window appears
694
mOkButton->clearFocus();
695
mOkButton->setFocusPolicy(Qt::ClickFocus); // don't allow keyboard selection
696
mOkButton->setFixedSize(mOkButton->sizeHint());
697
connect(mOkButton, SIGNAL(clicked()), SLOT(slotOk()));
698
grid->addWidget(mOkButton, 0, gridIndex++, Qt::AlignHCenter);
699
mOkButton->setWhatsThis(i18nc("@info:whatsthis", "Acknowledge the alarm"));
704
mEditButton = new PushButton(i18nc("@action:button", "&Edit..."), topWidget);
705
mEditButton->setFocusPolicy(Qt::ClickFocus); // don't allow keyboard selection
706
mEditButton->setFixedSize(mEditButton->sizeHint());
707
connect(mEditButton, SIGNAL(clicked()), SLOT(slotEdit()));
708
grid->addWidget(mEditButton, 0, gridIndex++, Qt::AlignHCenter);
709
mEditButton->setWhatsThis(i18nc("@info:whatsthis", "Edit the alarm."));
713
mDeferButton = new PushButton(i18nc("@action:button", "&Defer..."), topWidget);
714
mDeferButton->setFocusPolicy(Qt::ClickFocus); // don't allow keyboard selection
715
mDeferButton->setFixedSize(mDeferButton->sizeHint());
716
connect(mDeferButton, SIGNAL(clicked()), SLOT(slotDefer()));
717
grid->addWidget(mDeferButton, 0, gridIndex++, Qt::AlignHCenter);
718
mDeferButton->setWhatsThis(i18nc("@info:whatsthis", "<para>Defer the alarm until later.</para>"
719
"<para>You will be prompted to specify when the alarm should be redisplayed.</para>"));
722
mDeferButton->hide();
724
setDeferralLimit(mEvent); // ensure that button is disabled when alarm can't be deferred any more
726
if (!mAudioFile.isEmpty() && (mVolume || mFadeVolume > 0))
728
// Silence button to stop sound repetition
729
QPixmap pixmap = MainBarIcon("media-playback-stop");
730
mSilenceButton = new PushButton(topWidget);
731
mSilenceButton->setIcon(KIcon(pixmap));
732
grid->addWidget(mSilenceButton, 0, gridIndex++, Qt::AlignHCenter);
733
mSilenceButton->setToolTip(i18nc("@info:tooltip", "Stop sound"));
734
mSilenceButton->setWhatsThis(i18nc("@info:whatsthis", "Stop playing the sound"));
735
// To avoid getting in a mess, disable the button until sound playing has been set up
736
mSilenceButton->setEnabled(false);
739
KIconLoader iconLoader;
740
if (mKMailSerialNumber)
743
QPixmap pixmap = iconLoader.loadIcon(QLatin1String("internet-mail"), KIconLoader::MainToolbar);
744
mKMailButton = new PushButton(topWidget);
745
mKMailButton->setIcon(KIcon(pixmap));
746
connect(mKMailButton, SIGNAL(clicked()), SLOT(slotShowKMailMessage()));
747
grid->addWidget(mKMailButton, 0, gridIndex++, Qt::AlignHCenter);
748
mKMailButton->setToolTip(i18nc("@info:tooltip Locate this email in KMail", "Locate in <application>KMail</application>"));
749
mKMailButton->setWhatsThis(i18nc("@info:whatsthis", "Locate and highlight this email in <application>KMail</application>"));
753
QPixmap pixmap = iconLoader.loadIcon(KGlobal::mainComponent().aboutData()->appName(), KIconLoader::MainToolbar);
754
mKAlarmButton = new PushButton(topWidget);
755
mKAlarmButton->setIcon(KIcon(pixmap));
756
connect(mKAlarmButton, SIGNAL(clicked()), SLOT(displayMainWindow()));
757
grid->addWidget(mKAlarmButton, 0, gridIndex++, Qt::AlignHCenter);
758
mKAlarmButton->setToolTip(i18nc("@info:tooltip", "Activate <application>KAlarm</application>"));
759
mKAlarmButton->setWhatsThis(i18nc("@info:whatsthis", "Activate <application>KAlarm</application>"));
761
int butsize = mKAlarmButton->sizeHint().height();
763
butsize = qMax(butsize, mSilenceButton->sizeHint().height());
765
butsize = qMax(butsize, mKMailButton->sizeHint().height());
766
mKAlarmButton->setFixedSize(butsize, butsize);
768
mSilenceButton->setFixedSize(butsize, butsize);
770
mKMailButton->setFixedSize(butsize, butsize);
772
// Disable all buttons initially, to prevent accidental clicking on if they happen to be
773
// under the mouse just as the window appears.
774
mOkButton->setEnabled(false);
775
if (mDeferButton->isVisible())
776
mDeferButton->setEnabled(false);
778
mEditButton->setEnabled(false);
780
mKMailButton->setEnabled(false);
781
mKAlarmButton->setEnabled(false);
783
topLayout->activate();
784
setMinimumSize(QSize(grid->sizeHint().width() + 2*KDialog::marginHint(), sizeHint().height()));
785
bool modal = !(windowFlags() & Qt::X11BypassWindowManagerHint);
786
unsigned long wstate = (modal ? NET::Modal : 0) | NET::Sticky | NET::StaysOnTop;
788
KWindowSystem::setState(winid, wstate);
789
KWindowSystem::setOnAllDesktops(winid, true);
791
mInitialised = true; // the window's widgets have been created
759
794
/******************************************************************************
992
1031
void MessageWin::readProperties(const KConfigGroup& config)
994
mInvalid = config.readEntry("Invalid", false);
995
mEventID = config.readEntry("EventID");
996
mAlarmType = static_cast<KAAlarm::Type>(config.readEntry("AlarmType", 0));
997
if (mAlarmType == KAAlarm::INVALID_ALARM)
1000
kError() << "Invalid alarm: id=" << mEventID;
1002
mMessage = config.readEntry("Message");
1003
mAction = static_cast<KAEventData::Action>(config.readEntry("Type", 0));
1004
mFont = config.readEntry("Font", QFont());
1005
mBgColour = config.readEntry("BgColour", QColor(Qt::white));
1006
mFgColour = config.readEntry("FgColour", QColor(Qt::black));
1007
mConfirmAck = config.readEntry("ConfirmAck", false);
1008
QDateTime invalidDateTime;
1009
QDateTime dt = config.readEntry("Time", invalidDateTime);
1010
QString zone = config.readEntry("TimeZone");
1012
mDateTime = KDateTime(dt, KDateTime::ClockTime);
1013
else if (zone == QLatin1String("UTC"))
1015
dt.setTimeSpec(Qt::UTC);
1016
mDateTime = KDateTime(dt, KDateTime::UTC);
1020
KTimeZone tz = KSystemTimeZones::zone(zone);
1021
mDateTime = KDateTime(dt, (tz.isValid() ? tz : KSystemTimeZones::local()));
1023
bool dateOnly = config.readEntry("DateOnly", false);
1025
mDateTime.setDateOnly(true);
1026
mCloseTime = config.readEntry("Expiry", invalidDateTime);
1027
mAudioFile = config.readPathEntry("AudioFile", QString());
1028
mVolume = static_cast<float>(config.readEntry("Volume", 0)) / 100;
1031
if (!mAudioFile.isEmpty())
1032
mAudioRepeat = true;
1033
mSpeak = config.readEntry("Speak", false);
1034
mRestoreHeight = config.readEntry("Height", 0);
1035
mDefaultDeferMinutes = config.readEntry("DeferMins", 0);
1036
mNoDefer = config.readEntry("NoDefer", false);
1037
mNoPostAction = config.readEntry("NoPostAction", true);
1038
mKMailSerialNumber = static_cast<unsigned long>(config.readEntry("KMailSerial", QVariant(QVariant::ULongLong)).toULongLong());
1039
mCommandError = KAEvent::CmdErrType(config.readEntry("CmdErr", static_cast<int>(KAEvent::CMD_NO_ERROR)));
1040
mDontShowAgain = config.readEntry("DontShowAgain", QString());
1043
kDebug() << mEventID;
1044
if (mAlarmType != KAAlarm::INVALID_ALARM)
1046
// Recreate the event from the calendar file (if possible)
1047
if (!mEventID.isEmpty())
1049
AlarmCalendar* resources = AlarmCalendar::resources();
1050
KAEvent* event = resources->event(mEventID);
1054
mResource = resources->resourceForEvent(mEventID);
1059
// It's not in the active calendar, so try the displaying or archive calendars
1060
retrieveEvent(mEvent, mResource, mShowEdit, mNoDefer);
1061
mNoDefer = !mNoDefer;
1033
mInvalid = config.readEntry("Invalid", false);
1034
mEventID = config.readEntry("EventID");
1036
mEventItemId = config.readEntry("EventItemID", Akonadi::Item::Id(-1));
1038
mAlarmType = static_cast<KAAlarm::Type>(config.readEntry("AlarmType", 0));
1039
if (mAlarmType == KAAlarm::INVALID_ALARM)
1042
kError() << "Invalid alarm: id=" << mEventID;
1044
mMessage = config.readEntry("Message");
1045
mAction = static_cast<KAEvent::Action>(config.readEntry("Type", 0));
1046
mFont = config.readEntry("Font", QFont());
1047
mBgColour = config.readEntry("BgColour", QColor(Qt::white));
1048
mFgColour = config.readEntry("FgColour", QColor(Qt::black));
1049
mConfirmAck = config.readEntry("ConfirmAck", false);
1050
QDateTime invalidDateTime;
1051
QDateTime dt = config.readEntry("Time", invalidDateTime);
1052
QString zone = config.readEntry("TimeZone");
1054
mDateTime = KDateTime(dt, KDateTime::ClockTime);
1055
else if (zone == QLatin1String("UTC"))
1057
dt.setTimeSpec(Qt::UTC);
1058
mDateTime = KDateTime(dt, KDateTime::UTC);
1062
KTimeZone tz = KSystemTimeZones::zone(zone);
1063
mDateTime = KDateTime(dt, (tz.isValid() ? tz : KSystemTimeZones::local()));
1065
bool dateOnly = config.readEntry("DateOnly", false);
1067
mDateTime.setDateOnly(true);
1068
mCloseTime = config.readEntry("Expiry", invalidDateTime);
1069
mAudioFile = config.readPathEntry("AudioFile", QString());
1070
mVolume = static_cast<float>(config.readEntry("Volume", 0)) / 100;
1073
if (!mAudioFile.isEmpty())
1074
mAudioRepeat = true;
1075
mSpeak = config.readEntry("Speak", false);
1076
mRestoreHeight = config.readEntry("Height", 0);
1077
mDefaultDeferMinutes = config.readEntry("DeferMins", 0);
1078
mNoDefer = config.readEntry("NoDefer", false);
1079
mNoPostAction = config.readEntry("NoPostAction", true);
1080
mKMailSerialNumber = static_cast<unsigned long>(config.readEntry("KMailSerial", QVariant(QVariant::ULongLong)).toULongLong());
1081
mCommandError = KAEvent::CmdErrType(config.readEntry("CmdErr", static_cast<int>(KAEvent::CMD_NO_ERROR)));
1082
mDontShowAgain = config.readEntry("DontShowAgain", QString());
1085
mCollection = Akonadi::Collection();
1089
kDebug() << mEventID;
1090
if (mAlarmType != KAAlarm::INVALID_ALARM)
1092
// Recreate the event from the calendar file (if possible)
1093
if (!mEventID.isEmpty())
1095
KAEvent* event = AlarmCalendar::resources()->event(mEventID);
1100
mCollection = AkonadiModel::instance()->collectionForItem(mEventItemId);
1102
mResource = AlarmCalendar::resources()->resourceForEvent(mEventID);
1108
// It's not in the active calendar, so try the displaying or archive calendars
1110
retrieveEvent(mEvent, mCollection, mShowEdit, mNoDefer);
1112
retrieveEvent(mEvent, mResource, mShowEdit, mNoDefer);
1114
mNoDefer = !mNoDefer;
1068
1121
/******************************************************************************
1074
1127
void MessageWin::redisplayAlarms()
1076
AlarmCalendar* cal = AlarmCalendar::displayCalendar();
1080
AlarmResource* resource;
1081
KCal::Event::List events = cal->kcalEvents();
1082
for (int i = 0, end = events.count(); i < end; ++i)
1084
bool showDefer, showEdit;
1085
reinstateFromDisplaying(events[i], event, resource, showEdit, showDefer);
1086
if (!findEvent(event.id()))
1088
// This event should be displayed, but currently isn't being
1089
KAAlarm alarm = event.convertDisplayingAlarm();
1090
if (alarm.type() == KAAlarm::INVALID_ALARM)
1092
kError() << "Invalid alarm: id=" << event.id();
1095
kDebug() << event.id();
1096
bool login = alarm.repeatAtLogin();
1097
int flags = NO_RESCHEDULE | (login ? NO_DEFER : 0) | NO_INIT_VIEW;
1098
MessageWin* win = new MessageWin(&event, alarm, flags);
1099
win->mResource = resource;
1100
bool rw = resource && resource->writable();
1101
win->mShowEdit = rw ? showEdit : false;
1102
win->mNoDefer = (rw && !login) ? !showDefer : true;
1129
AlarmCalendar* cal = AlarmCalendar::displayCalendar();
1134
Akonadi::Collection collection;
1136
AlarmResource* resource;
1138
Event::List events = cal->kcalEvents();
1139
for (int i = 0, end = events.count(); i < end; ++i)
1141
bool showDefer, showEdit;
1143
reinstateFromDisplaying(events[i], event, collection, showEdit, showDefer);
1145
reinstateFromDisplaying(events[i], event, resource, showEdit, showDefer);
1147
if (!findEvent(event.id()))
1149
// This event should be displayed, but currently isn't being
1150
KAAlarm alarm = event.convertDisplayingAlarm();
1151
if (alarm.type() == KAAlarm::INVALID_ALARM)
1153
kError() << "Invalid alarm: id=" << event.id();
1156
kDebug() << event.id();
1157
bool login = alarm.repeatAtLogin();
1158
int flags = NO_RESCHEDULE | (login ? NO_DEFER : 0) | NO_INIT_VIEW;
1159
MessageWin* win = new MessageWin(&event, alarm, flags);
1161
win->mCollection = collection;
1162
bool rw = CollectionControlModel::isWritable(collection, event.category());
1164
win->mResource = resource;
1165
bool rw = resource && resource->writable();
1167
win->mShowEdit = rw ? showEdit : false;
1168
win->mNoDefer = (rw && !login) ? !showDefer : true;
1110
1176
/******************************************************************************
1111
1177
* Retrieves the event with the current ID from the displaying calendar file,
1112
1178
* or if not found there, from the archive calendar.
1181
bool MessageWin::retrieveEvent(KAEvent& event, Akonadi::Collection& resource, bool& showEdit, bool& showDefer)
1114
1183
bool MessageWin::retrieveEvent(KAEvent& event, AlarmResource*& resource, bool& showEdit, bool& showDefer)
1116
const Event* kcalEvent = AlarmCalendar::displayCalendar()->kcalEvent(KCalEvent::uid(mEventID, KCalEvent::DISPLAYING));
1117
if (!reinstateFromDisplaying(kcalEvent, event, resource, showEdit, showDefer))
1119
// The event isn't in the displaying calendar.
1120
// Try to retrieve it from the archive calendar.
1121
KAEvent* ev = AlarmCalendar::resources()->event(KCalEvent::uid(mEventID, KCalEvent::ARCHIVED));
1125
event.setArchive(); // ensure that it gets re-archived if it's saved
1126
event.setCategory(KCalEvent::ACTIVE);
1127
if (mEventID != event.id())
1128
kError() << "Wrong event ID";
1129
event.setEventId(mEventID);
1133
kDebug() << event.id() << ": success";
1187
ConstEventPtr kcalEvent = AlarmCalendar::displayCalendar()->kcalEvent(KAlarm::CalEvent::uid(mEventID, KAlarm::CalEvent::DISPLAYING));
1189
const Event* kcalEvent = AlarmCalendar::displayCalendar()->kcalEvent(KAlarm::CalEvent::uid(mEventID, KAlarm::CalEvent::DISPLAYING));
1191
if (!reinstateFromDisplaying(kcalEvent, event, resource, showEdit, showDefer))
1193
// The event isn't in the displaying calendar.
1194
// Try to retrieve it from the archive calendar.
1195
KAEvent* ev = AlarmCalendar::resources()->event(KAlarm::CalEvent::uid(mEventID, KAlarm::CalEvent::ARCHIVED));
1199
event.setArchive(); // ensure that it gets re-archived if it's saved
1200
event.setCategory(KAlarm::CalEvent::ACTIVE);
1201
if (mEventID != event.id())
1202
kError() << "Wrong event ID";
1203
event.setEventId(mEventID);
1205
resource = Akonadi::Collection();
1211
kDebug() << event.id() << ": success";
1138
1216
/******************************************************************************
1139
1217
* Retrieves the displayed event from the calendar file, or if not found there,
1140
1218
* from the displaying calendar.
1221
bool MessageWin::reinstateFromDisplaying(const ConstEventPtr& kcalEvent, KAEvent& event, Akonadi::Collection& collection, bool& showEdit, bool& showDefer)
1142
1223
bool MessageWin::reinstateFromDisplaying(const Event* kcalEvent, KAEvent& event, AlarmResource*& resource, bool& showEdit, bool& showDefer)
1147
event.reinstateFromDisplaying(kcalEvent, resourceID, showEdit, showDefer);
1148
resource = AlarmResources::instance()->resourceWithId(resourceID);
1149
if (resource && !resource->isOpen())
1151
event.clearResourceId();
1152
kDebug() << event.id() << ": success";
1229
Akonadi::Collection::Id collectionId;
1230
event.reinstateFromDisplaying(kcalEvent, collectionId, showEdit, showDefer);
1231
collection = AkonadiModel::instance()->collectionById(collectionId);
1232
event.clearCollectionId();
1235
event.reinstateFromDisplaying(kcalEvent, resourceID, showEdit, showDefer);
1236
resource = AlarmResources::instance()->resourceWithId(resourceID);
1237
if (resource && !resource->isOpen())
1239
event.clearResourceId();
1241
kDebug() << event.id() << ": success";
1156
1245
/******************************************************************************
1689
1790
void MessageWin::showEvent(QShowEvent* se)
1691
MainWindowBase::showEvent(se);
1694
if (mErrorWindow || mAlarmType == KAAlarm::INVALID_ALARM)
1696
// Don't bother repositioning error messages,
1697
// and invalid alarms should be deleted anyway.
1702
/* Set the window size.
1703
* Note that the frame thickness is not yet known when this
1704
* method is called, so for large windows the size needs to be
1707
bool execComplete = true;
1708
QSize s = sizeHint(); // fit the window round the message
1709
if (mAction == KAEventData::FILE && !mErrorMsgs.count())
1710
KAlarm::readConfigWindowSize("FileMessage", s);
1713
QRect desk = KAlarm::desktopWorkArea(mScreenNumber);
1714
QRect frame = frameGeometry();
1716
mButtonDelay = Preferences::messageButtonDelay() * 1000;
1719
// Position the window in the middle of the screen, and
1720
// delay enabling the buttons.
1721
mPositioning = true;
1722
move((desk.width() - frame.width())/2, (desk.height() - frame.height())/2);
1723
execComplete = false;
1727
/* Try to ensure that the window can't accidentally be acknowledged
1728
* by the user clicking the mouse just as it appears.
1729
* To achieve this, move the window so that the OK button is as far away
1730
* from the cursor as possible. If the buttons are still too close to the
1731
* cursor, disable the buttons for a short time.
1732
* N.B. This can't be done in show(), since the geometry of the window
1733
* is not known until it is displayed. Unfortunately by moving the
1734
* window in showEvent(), a flicker is unavoidable.
1735
* See the Qt documentation on window geometry for more details.
1737
// PROBLEM: The frame size is not known yet!
1738
QPoint cursor = QCursor::pos();
1739
QRect rect = geometry();
1740
// Find the offsets from the outside of the frame to the edges of the OK button
1741
QRect button(mOkButton->mapToParent(QPoint(0, 0)), mOkButton->mapToParent(mOkButton->rect().bottomRight()));
1742
int buttonLeft = button.left() + rect.left() - frame.left();
1743
int buttonRight = width() - button.right() + frame.right() - rect.right();
1744
int buttonTop = button.top() + rect.top() - frame.top();
1745
int buttonBottom = height() - button.bottom() + frame.bottom() - rect.bottom();
1747
int centrex = (desk.width() + buttonLeft - buttonRight) / 2;
1748
int centrey = (desk.height() + buttonTop - buttonBottom) / 2;
1749
int x = (cursor.x() < centrex) ? desk.right() - frame.width() : desk.left();
1750
int y = (cursor.y() < centrey) ? desk.bottom() - frame.height() : desk.top();
1752
// Find the enclosing rectangle for the new button positions
1753
// and check if the cursor is too near
1754
QRect buttons = mOkButton->geometry().unite(mKAlarmButton->geometry());
1755
buttons.translate(rect.left() + x - frame.left(), rect.top() + y - frame.top());
1756
int minDistance = proximityMultiple * mOkButton->height();
1757
if ((abs(cursor.x() - buttons.left()) < minDistance
1758
|| abs(cursor.x() - buttons.right()) < minDistance)
1759
&& (abs(cursor.y() - buttons.top()) < minDistance
1760
|| abs(cursor.y() - buttons.bottom()) < minDistance))
1761
mButtonDelay = proximityButtonDelay; // too near - disable buttons initially
1763
if (x != frame.left() || y != frame.top())
1765
mPositioning = true;
1767
execComplete = false;
1771
displayComplete(); // play audio, etc.
1774
// Set the window size etc. once the frame size is known
1775
QTimer::singleShot(0, this, SLOT(frameDrawn()));
1792
MainWindowBase::showEvent(se);
1795
if (mErrorWindow || mAlarmType == KAAlarm::INVALID_ALARM)
1797
// Don't bother repositioning error messages,
1798
// and invalid alarms should be deleted anyway.
1803
/* Set the window size.
1804
* Note that the frame thickness is not yet known when this
1805
* method is called, so for large windows the size needs to be
1808
bool execComplete = true;
1809
QSize s = sizeHint(); // fit the window round the message
1810
if (mAction == KAEvent::FILE && !mErrorMsgs.count())
1811
KAlarm::readConfigWindowSize("FileMessage", s);
1814
QRect desk = KAlarm::desktopWorkArea(mScreenNumber);
1815
QRect frame = frameGeometry();
1817
mButtonDelay = Preferences::messageButtonDelay() * 1000;
1820
// Position the window in the middle of the screen, and
1821
// delay enabling the buttons.
1822
mPositioning = true;
1823
move((desk.width() - frame.width())/2, (desk.height() - frame.height())/2);
1824
execComplete = false;
1828
/* Try to ensure that the window can't accidentally be acknowledged
1829
* by the user clicking the mouse just as it appears.
1830
* To achieve this, move the window so that the OK button is as far away
1831
* from the cursor as possible. If the buttons are still too close to the
1832
* cursor, disable the buttons for a short time.
1833
* N.B. This can't be done in show(), since the geometry of the window
1834
* is not known until it is displayed. Unfortunately by moving the
1835
* window in showEvent(), a flicker is unavoidable.
1836
* See the Qt documentation on window geometry for more details.
1838
// PROBLEM: The frame size is not known yet!
1839
QPoint cursor = QCursor::pos();
1840
QRect rect = geometry();
1841
// Find the offsets from the outside of the frame to the edges of the OK button
1842
QRect button(mOkButton->mapToParent(QPoint(0, 0)), mOkButton->mapToParent(mOkButton->rect().bottomRight()));
1843
int buttonLeft = button.left() + rect.left() - frame.left();
1844
int buttonRight = width() - button.right() + frame.right() - rect.right();
1845
int buttonTop = button.top() + rect.top() - frame.top();
1846
int buttonBottom = height() - button.bottom() + frame.bottom() - rect.bottom();
1848
int centrex = (desk.width() + buttonLeft - buttonRight) / 2;
1849
int centrey = (desk.height() + buttonTop - buttonBottom) / 2;
1850
int x = (cursor.x() < centrex) ? desk.right() - frame.width() : desk.left();
1851
int y = (cursor.y() < centrey) ? desk.bottom() - frame.height() : desk.top();
1853
// Find the enclosing rectangle for the new button positions
1854
// and check if the cursor is too near
1855
QRect buttons = mOkButton->geometry().unite(mKAlarmButton->geometry());
1856
buttons.translate(rect.left() + x - frame.left(), rect.top() + y - frame.top());
1857
int minDistance = proximityMultiple * mOkButton->height();
1858
if ((abs(cursor.x() - buttons.left()) < minDistance
1859
|| abs(cursor.x() - buttons.right()) < minDistance)
1860
&& (abs(cursor.y() - buttons.top()) < minDistance
1861
|| abs(cursor.y() - buttons.bottom()) < minDistance))
1862
mButtonDelay = proximityButtonDelay; // too near - disable buttons initially
1864
if (x != frame.left() || y != frame.top())
1866
mPositioning = true;
1868
execComplete = false;
1872
displayComplete(); // play audio, etc.
1875
// Set the window size etc. once the frame size is known
1876
QTimer::singleShot(0, this, SLOT(frameDrawn()));
1780
1881
/******************************************************************************
2053
2158
void MessageWin::slotDefer()
2055
mDeferDlg = new DeferAlarmDlg(KDateTime::currentDateTime(Preferences::timeZone()).addSecs(60), mDateTime.isDateOnly(), false, this);
2056
mDeferDlg->setObjectName("DeferDlg"); // used by LikeBack
2057
mDeferDlg->setDeferMinutes(mDefaultDeferMinutes > 0 ? mDefaultDeferMinutes : Preferences::defaultDeferTime());
2058
mDeferDlg->setLimit(mEventID);
2059
if (!Preferences::modalMessages())
2061
if (mDeferDlg->exec() == QDialog::Accepted)
2063
DateTime dateTime = mDeferDlg->getDateTime();
2064
int delayMins = mDeferDlg->deferMinutes();
2065
// Fetch the up-to-date alarm from the calendar. Note that it could have
2066
// changed since it was displayed.
2067
const KAEvent* event = mEventID.isNull() ? 0 : AlarmCalendar::resources()->event(mEventID);
2070
// The event still exists in the active calendar
2071
kDebug() << "Deferring event" << mEventID;
2072
KAEvent newev(*event);
2073
newev.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM), true);
2074
newev.setDeferDefaultMinutes(delayMins);
2075
KAlarm::updateEvent(newev, mDeferDlg, true);
2076
if (newev.deferred())
2077
mNoPostAction = true;
2081
// Try to retrieve the event from the displaying or archive calendars
2082
AlarmResource* resource = 0;
2084
bool showEdit, showDefer;
2085
if (!retrieveEvent(event, resource, showEdit, showDefer))
2087
// The event doesn't exist any more !?!, so recurrence data,
2088
// flags, and more, have been lost.
2089
KMessageBox::error(this, i18nc("@info", "<para>Cannot defer alarm:</para><para>Alarm not found.</para>"));
2093
mDeferButton->setEnabled(false);
2094
mEditButton->setEnabled(false);
2097
kDebug() << "Deferring retrieved event" << mEventID;
2098
event.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM), true);
2099
event.setDeferDefaultMinutes(delayMins);
2100
event.setCommandError(mCommandError);
2101
// Add the event back into the calendar file, retaining its ID
2102
// and not updating KOrganizer.
2103
KAlarm::addEvent(event, resource, mDeferDlg, KAlarm::USE_EVENT_ID);
2104
if (event.deferred())
2105
mNoPostAction = true;
2106
// Finally delete it from the archived calendar now that it has
2107
// been reactivated.
2108
event.setCategory(KCalEvent::ARCHIVED);
2109
KAlarm::deleteEvent(event, false);
2111
if (theApp()->wantShowInSystemTray())
2113
// Alarms are to be displayed only if the system tray icon is running,
2114
// so start it if necessary so that the deferred alarm will be shown.
2115
theApp()->displayTrayIcon(true);
2117
mNoCloseConfirm = true; // allow window to close without confirmation prompt
2160
mDeferDlg = new DeferAlarmDlg(KDateTime::currentDateTime(Preferences::timeZone()).addSecs(60), mDateTime.isDateOnly(), false, this);
2161
mDeferDlg->setObjectName("DeferDlg"); // used by LikeBack
2162
mDeferDlg->setDeferMinutes(mDefaultDeferMinutes > 0 ? mDefaultDeferMinutes : Preferences::defaultDeferTime());
2163
mDeferDlg->setLimit(mEventID);
2164
if (!Preferences::modalMessages())
2166
if (mDeferDlg->exec() == QDialog::Accepted)
2168
DateTime dateTime = mDeferDlg->getDateTime();
2169
int delayMins = mDeferDlg->deferMinutes();
2170
// Fetch the up-to-date alarm from the calendar. Note that it could have
2171
// changed since it was displayed.
2172
const KAEvent* event = mEventID.isNull() ? 0 : AlarmCalendar::resources()->event(mEventID);
2175
// The event still exists in the active calendar
2176
kDebug() << "Deferring event" << mEventID;
2177
KAEvent newev(*event);
2178
newev.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM), true);
2179
newev.setDeferDefaultMinutes(delayMins);
2180
KAlarm::updateEvent(newev, mDeferDlg, true);
2181
if (newev.deferred())
2182
mNoPostAction = true;
2186
// Try to retrieve the event from the displaying or archive calendars
2188
Akonadi::Collection collection;
2190
AlarmResource* resource = 0;
2193
bool showEdit, showDefer;
2195
if (!retrieveEvent(event, collection, showEdit, showDefer))
2197
if (!retrieveEvent(event, resource, showEdit, showDefer))
2200
// The event doesn't exist any more !?!, so recurrence data,
2201
// flags, and more, have been lost.
2202
KMessageBox::error(this, i18nc("@info", "<para>Cannot defer alarm:</para><para>Alarm not found.</para>"));
2206
mDeferButton->setEnabled(false);
2207
mEditButton->setEnabled(false);
2210
kDebug() << "Deferring retrieved event" << mEventID;
2211
event.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM), true);
2212
event.setDeferDefaultMinutes(delayMins);
2213
event.setCommandError(mCommandError);
2214
// Add the event back into the calendar file, retaining its ID
2215
// and not updating KOrganizer.
2217
KAlarm::addEvent(event, &collection, mDeferDlg, KAlarm::USE_EVENT_ID);
2219
KAlarm::addEvent(event, resource, mDeferDlg, KAlarm::USE_EVENT_ID);
2221
if (event.deferred())
2222
mNoPostAction = true;
2223
// Finally delete it from the archived calendar now that it has
2224
// been reactivated.
2225
event.setCategory(KAlarm::CalEvent::ARCHIVED);
2226
KAlarm::deleteEvent(event, false);
2228
if (theApp()->wantShowInSystemTray())
2230
// Alarms are to be displayed only if the system tray icon is running,
2231
// so start it if necessary so that the deferred alarm will be shown.
2232
theApp()->displayTrayIcon(true);
2234
mNoCloseConfirm = true; // allow window to close without confirmation prompt
2126
2243
/******************************************************************************