22 #include "messagewin_p.moc"
23 #include "messagewin.moc"
42 #include "kspeechinterface.h"
44 #include <kstandarddirs.h>
46 #include <kstandardguiitem.h>
47 #include <kaboutdata.h>
50 #include <kiconloader.h>
52 #include <ktextbrowser.h>
53 #include <ksystemtimezone.h>
54 #include <kglobalsettings.h>
55 #include <kmimetype.h>
56 #include <ktextedit.h>
57 #include <kwindowsystem.h>
58 #include <kio/netaccess.h>
59 #include <knotification.h>
60 #include <kpushbutton.h>
61 #include <ksqueezedtextlabel.h>
62 #include <phonon/mediaobject.h>
63 #include <phonon/audiooutput.h>
64 #include <phonon/volumefadereffect.h>
66 #include <ktoolinvocation.h>
73 #include <QtDBus/QtDBus>
83 #include <QGridLayout>
84 #include <QVBoxLayout>
85 #include <QHBoxLayout>
86 #include <QResizeEvent>
87 #include <QCloseEvent>
88 #include <QDesktopWidget>
89 #include <QMutexLocker>
95 using namespace KCalCore;
99 using namespace KAlarmCal;
102 enum FullScreenType { NoFullScreen = 0, FullScreen = 1, FullScreenActive = 2 };
103 static FullScreenType haveFullScreenWindow(
int screen);
104 static FullScreenType findFullScreenWindows(
const QVector<QRect>& screenRects, QVector<FullScreenType>& screenTypes);
107 #ifdef KMAIL_SUPPORTED
108 #include "kmailinterface.h"
109 static const QLatin1String KMAIL_DBUS_SERVICE(
"org.kde.kmail");
110 static const QLatin1String KMAIL_DBUS_PATH(
"/KMail");
122 MessageText(
QWidget* parent = 0)
127 setFrameStyle(NoFrame);
128 setLineWrapMode(NoWrap);
130 int scrollBarHeight()
const {
return horizontalScrollBar()->height(); }
131 int scrollBarWidth()
const {
return verticalScrollBar()->width(); }
132 void setBackgroundColour(
const QColor& c)
134 QPalette pal = viewport()->palette();
135 pal.setColor(viewport()->backgroundRole(), c);
136 viewport()->setPalette(pal);
138 virtual QSize sizeHint()
const
140 QSizeF docsize = document()->size();
141 return QSize(static_cast<int>(docsize.width() + 0.99) + verticalScrollBar()->width(),
142 static_cast<int>(docsize.height() + 0.99) + horizontalScrollBar()->height());
144 bool newLine()
const {
return mNewLine; }
145 void setNewLine(
bool nl) { mNewLine = nl; }
152 static const Qt::WindowFlags
WFLAGS = Qt::WindowStaysOnTopHint;
153 static const Qt::WindowFlags
WFLAGS2 = Qt::WindowContextHelpButtonHint;
154 static const Qt::WidgetAttribute
WidgetFlags = Qt::WA_DeleteOnClose;
165 QMap<EventId, unsigned> MessageWin::mErrorMessages;
167 QMap<QString, unsigned> MessageWin::mErrorMessages;
182 :
MainWindowBase(0, static_cast<Qt::WindowFlags>(
WFLAGS |
WFLAGS2 | ((flags & ALWAYS_HIDE) || getWorkAreaAndModal() ? Qt::WindowType(0) : Qt::X11BypassWindowManagerHint))),
183 mMessage(event->cleanText()),
184 mFont(event->font()),
185 mBgColour(event->bgColour()),
186 mFgColour(event->fgColour()),
188 mEventItemId(event->itemId()),
191 mEventId(event->id()),
193 mAudioFile(event->audioFile()),
194 mVolume(event->soundVolume()),
195 mFadeVolume(event->fadeVolume()),
196 mFadeSeconds(qMin(event->fadeSeconds(), 86400)),
197 mDefaultDeferMinutes(event->deferDefaultMinutes()),
198 mAlarmType(alarm.type()),
199 mAction(event->actionSubType()),
200 #ifdef KMAIL_SUPPORTED
201 mKMailSerialNumber(event->kmailSerialNumber()),
203 mKMailSerialNumber(0),
205 mCommandError(event->commandError()),
207 mAudioRepeatPause(event->repeatSoundPause()),
208 mConfirmAck(event->confirmAck()),
212 mOriginalEvent(*event),
214 mCollection(
AlarmCalendar::resources()->collectionForEvent(mEventItemId)),
216 mResource(
AlarmCalendar::resources()->resourceForEvent(mEventId)),
225 mDontShowAgainCheck(0),
228 mAlwaysHide(flags & ALWAYS_HIDE),
231 mNoPostAction(alarm.type() & KAAlarm::REMINDER_ALARM),
233 mBeep(event->beep()),
234 mSpeak(event->speak()),
235 mRescheduleEvent(!(flags & NO_RESCHEDULE)),
238 mNoCloseConfirm(false),
239 mDisableDeferral(false)
242 setAttribute(static_cast<Qt::WidgetAttribute>(
WidgetFlags));
243 setWindowModality(Qt::WindowModal);
244 setObjectName(QLatin1String(
"MessageWin"));
245 if (alarm.type() & KAAlarm::REMINDER_ALARM)
247 if (event->reminderMinutes() < 0)
249 event->previousOccurrence(alarm.dateTime(
false).effectiveKDateTime(), mDateTime,
false);
250 if (!mDateTime.isValid() &&
event->repeatAtLogin())
251 mDateTime = alarm.dateTime().addSecs(event->reminderMinutes() * 60);
254 mDateTime =
event->mainDateTime(
true);
257 mDateTime = alarm.dateTime(
true);
265 mShowEdit = !mEventId.isEmpty() && !readonly;
266 mNoDefer = readonly || (flags &
NO_DEFER) || alarm.repeatAtLogin();
271 setAutoSaveSettings(QLatin1String(
"MessageWin"),
false);
272 mWindowList.append(
this);
273 if (event->autoClose())
274 mCloseTime = alarm.dateTime().effectiveKDateTime().toUtc().dateTime().addSecs(event->lateCancel() * 60);
288 const QStringList& errmsgs,
const QString& dontShowAgain)
291 if (!dontShowAgain.isEmpty()
292 && KAlarm::dontShowErrors(
EventId(event), dontShowAgain))
294 if (!dontShowAgain.isEmpty()
295 && KAlarm::dontShowErrors(event.id(), dontShowAgain))
300 for (
int i = 0, end = mWindowList.count(); i < end; ++i)
304 if (w->mErrorWindow && w->mEventId ==
EventId(event)
305 && w->mErrorMsgs == errmsgs && w->mDontShowAgain == dontShowAgain)
307 if (w->mErrorWindow && w->mEventId == event.id()
308 && w->mErrorMsgs == errmsgs && w->mDontShowAgain == dontShowAgain)
313 (
new MessageWin(&event, alarmDateTime, errmsgs, dontShowAgain))->
show();
322 const QStringList& errmsgs,
const QString& dontShowAgain)
324 mMessage(event->cleanText()),
325 mDateTime(alarmDateTime),
327 mEventItemId(event->itemId()),
330 mEventId(event->id()),
332 mAlarmType(KAAlarm::MAIN_ALARM),
333 mAction(event->actionSubType()),
334 mKMailSerialNumber(0),
335 mCommandError(KAEvent::CMD_NO_ERROR),
337 mDontShowAgain(dontShowAgain),
344 mOriginalEvent(*event),
355 mDontShowAgainCheck(0),
363 mRescheduleEvent(false),
366 mNoCloseConfirm(false),
367 mDisableDeferral(false)
369 kDebug() <<
"errmsg";
370 setAttribute(static_cast<Qt::WidgetAttribute>(
WidgetFlags));
371 setWindowModality(Qt::WindowModal);
372 setObjectName(QLatin1String(
"ErrorWin"));
373 getWorkAreaAndModal();
375 mWindowList.append(
this);
391 mDontShowAgainCheck(0),
398 mRescheduleEvent(false),
401 mNoCloseConfirm(false),
402 mDisableDeferral(false)
404 kDebug() <<
"restore";
406 setWindowModality(Qt::WindowModal);
407 setObjectName(QLatin1String(
"RestoredMsgWin"));
408 getWorkAreaAndModal();
409 mWindowList.append(
this);
417 kDebug() << mEventId;
419 mAudioThread->quit();
420 mErrorMessages.remove(mEventId);
421 mWindowList.removeAll(
this);
424 if (!mNoPostAction && !mEvent.postAction().isEmpty())
434 void MessageWin::initView()
436 bool reminder = (!mErrorWindow && (mAlarmType & KAAlarm::REMINDER_ALARM));
437 int leading = fontMetrics().leading();
438 setCaption((mAlarmType & KAAlarm::REMINDER_ALARM) ? i18nc(
"@title:window",
"Reminder") : i18nc(
"@title:window",
"Message"));
440 setCentralWidget(topWidget);
441 QVBoxLayout* topLayout =
new QVBoxLayout(topWidget);
442 topLayout->setMargin(KDialog::marginHint());
443 topLayout->setSpacing(KDialog::spacingHint());
445 QPalette labelPalette = palette();
446 labelPalette.setColor(backgroundRole(), labelPalette.color(QPalette::Window));
450 mTimeLabel =
new QLabel(topWidget);
451 mTimeLabel->setText(dateTimeToDisplay());
452 mTimeLabel->setFrameStyle(QFrame::StyledPanel);
453 mTimeLabel->setPalette(labelPalette);
454 mTimeLabel->setAutoFillBackground(
true);
455 topLayout->addWidget(mTimeLabel, 0, Qt::AlignHCenter);
456 mTimeLabel->setWhatsThis(i18nc(
"@info:whatsthis",
"The scheduled date/time for the message (as opposed to the actual time of display)."));
458 if (mDateTime.isValid())
463 QString s = i18nc(
"@info",
"Reminder");
464 QRegExp re(QLatin1String(
"^(<[^>]+>)*"));
466 s.insert(re.matchedLength(), mTimeLabel->text() + QLatin1String(
"<br/>"));
467 mTimeLabel->setText(s);
468 mTimeLabel->setAlignment(Qt::AlignHCenter);
482 KSqueezedTextLabel* label =
new KSqueezedTextLabel(mMessage, topWidget);
483 label->setFrameStyle(QFrame::StyledPanel);
484 label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
485 label->setPalette(labelPalette);
486 label->setAutoFillBackground(
true);
487 label->setWhatsThis(i18nc(
"@info:whatsthis",
"The file whose contents are displayed below"));
488 topLayout->addWidget(label, 0, Qt::AlignHCenter);
497 QFile qfile(tmpFile);
498 QFileInfo info(qfile);
499 if (!(dir = info.isDir()))
502 KTextBrowser* view =
new KTextBrowser(topWidget);
503 view->setFrameStyle(QFrame::NoFrame);
504 view->setWordWrapMode(QTextOption::NoWrap);
505 QPalette pal = view->viewport()->palette();
506 pal.setColor(view->viewport()->backgroundRole(), mBgColour);
507 view->viewport()->setPalette(pal);
508 view->setTextColor(mFgColour);
509 view->setCurrentFont(mFont);
510 KMimeType::Ptr mime = KMimeType::findByUrl(url);
511 if (mime->is(QLatin1String(
"application/octet-stream")))
512 mime = KMimeType::findByFileContent(tmpFile);
513 switch (KAlarm::fileType(mime))
516 view->setHtml(QLatin1String(
"<img source=\"") + tmpFile + QLatin1String(
"\">"));
518 case KAlarm::TextFormatted:
519 view->QTextBrowser::setSource(tmpFile);
524 if (qfile.open(QIODevice::ReadOnly))
526 QTextStream str(&qfile);
528 view->setPlainText(str.readAll());
534 view->setMinimumSize(view->sizeHint());
535 topLayout->addWidget(view);
541 int h = 20*view->fontMetrics().lineSpacing() + 2*view->frameWidth();
542 view->resize(QSize(h, h).expandedTo(view->sizeHint()));
543 view->setWhatsThis(i18nc(
"@info:whatsthis",
"The contents of the file to be displayed"));
545 KIO::NetAccess::removeTempFile(tmpFile);
551 mErrorMsgs += dir ? i18nc(
"@info",
"File is a folder") : exists ? i18nc(
"@info",
"Failed to open file") : i18nc(
"@info",
"File not found");
555 case KAEvent::MESSAGE:
559 MessageText*
text =
new MessageText(topWidget);
560 text->setAutoFillBackground(
true);
561 text->setBackgroundColour(mBgColour);
562 text->setTextColor(mFgColour);
563 text->setCurrentFont(mFont);
564 text->insertPlainText(mMessage);
565 int lineSpacing = text->fontMetrics().lineSpacing();
566 QSize s = text->sizeHint();
568 text->setMaximumHeight(h + text->scrollBarHeight());
569 text->setMinimumHeight(qMin(h, lineSpacing*4));
570 text->setMaximumWidth(s.width() + text->scrollBarWidth());
571 text->setWhatsThis(i18nc(
"@info:whatsthis",
"The alarm message"));
572 int vspace = lineSpacing/2;
573 int hspace = lineSpacing - KDialog::marginHint();
574 topLayout->addSpacing(vspace);
575 topLayout->addStretch();
578 topLayout->addWidget(text, 1, Qt::AlignHCenter);
581 QHBoxLayout* layout =
new QHBoxLayout();
582 layout->addSpacing(hspace);
583 layout->addWidget(text, 1, Qt::AlignHCenter);
584 layout->addSpacing(hspace);
585 topLayout->addLayout(layout);
588 topLayout->addStretch();
591 case KAEvent::COMMAND:
593 mCommandText =
new MessageText(topWidget);
594 mCommandText->setBackgroundColour(mBgColour);
595 mCommandText->setTextColor(mFgColour);
596 mCommandText->setCurrentFont(mFont);
597 topLayout->addWidget(mCommandText);
598 mCommandText->setWhatsThis(i18nc(
"@info:whatsthis",
"The output of the alarm's command"));
607 if (reminder && mEvent.reminderMinutes() > 0)
610 mRemainingText =
new QLabel(topWidget);
611 mRemainingText->setFrameStyle(QFrame::Box | QFrame::Raised);
612 mRemainingText->setMargin(leading);
613 mRemainingText->setPalette(labelPalette);
614 mRemainingText->setAutoFillBackground(
true);
615 if (mDateTime.isDateOnly() || KDateTime::currentLocalDate().daysTo(mDateTime.date()) > 0)
617 setRemainingTextDay();
622 setRemainingTextMinute();
625 topLayout->addWidget(mRemainingText, 0, Qt::AlignHCenter);
626 topLayout->addSpacing(KDialog::spacingHint());
627 topLayout->addStretch();
639 frame->setFrameStyle(QFrame::Box | QFrame::Raised);
640 frame->setWhatsThis(i18nc(
"@info:whatsthis",
"The email to send"));
641 topLayout->addWidget(frame, 0, Qt::AlignHCenter);
642 QGridLayout* grid =
new QGridLayout(frame);
643 grid->setMargin(KDialog::marginHint());
644 grid->setSpacing(KDialog::spacingHint());
646 QLabel* label =
new QLabel(i18nc(
"@info Email addressee",
"To:"), frame);
647 label->setFixedSize(label->sizeHint());
648 grid->addWidget(label, 0, 0, Qt::AlignLeft);
649 label =
new QLabel(mEvent.emailAddresses(QLatin1String(
"\n")), frame);
650 label->setFixedSize(label->sizeHint());
651 grid->addWidget(label, 0, 1, Qt::AlignLeft);
653 label =
new QLabel(i18nc(
"@info Email subject",
"Subject:"), frame);
654 label->setFixedSize(label->sizeHint());
655 grid->addWidget(label, 1, 0, Qt::AlignLeft);
656 label =
new QLabel(mEvent.emailSubject(), frame);
657 label->setFixedSize(label->sizeHint());
658 grid->addWidget(label, 1, 1, Qt::AlignLeft);
661 case KAEvent::COMMAND:
663 case KAEvent::MESSAGE:
670 if (!mErrorMsgs.count())
672 topWidget->setAutoFillBackground(
true);
673 QPalette palette = topWidget->palette();
674 palette.setColor(topWidget->backgroundRole(), mBgColour);
675 topWidget->setPalette(palette);
679 setCaption(i18nc(
"@title:window",
"Error"));
680 QHBoxLayout* layout =
new QHBoxLayout();
681 layout->setMargin(2*KDialog::marginHint());
682 layout->addStretch();
683 topLayout->addLayout(layout);
685 label->setPixmap(DesktopIcon(QLatin1String(
"dialog-error")));
686 label->setFixedSize(label->sizeHint());
687 layout->addWidget(label, 0, Qt::AlignRight);
688 QVBoxLayout* vlayout =
new QVBoxLayout();
689 layout->addLayout(vlayout);
690 for (QStringList::Iterator it = mErrorMsgs.begin(); it != mErrorMsgs.end(); ++it)
692 label =
new QLabel(*it, topWidget);
693 label->setFixedSize(label->sizeHint());
694 vlayout->addWidget(label, 0, Qt::AlignLeft);
696 layout->addStretch();
697 if (!mDontShowAgain.isEmpty())
699 mDontShowAgainCheck =
new QCheckBox(i18nc(
"@option:check",
"Do not display this error message again for this alarm"), topWidget);
700 mDontShowAgainCheck->setFixedSize(mDontShowAgainCheck->sizeHint());
701 topLayout->addWidget(mDontShowAgainCheck, 0, Qt::AlignLeft);
705 QGridLayout* grid =
new QGridLayout();
706 grid->setColumnStretch(0, 1);
707 topLayout->addLayout(grid);
711 mOkButton =
new PushButton(KStandardGuiItem::close(), topWidget);
713 mOkButton->clearFocus();
714 mOkButton->setFocusPolicy(Qt::ClickFocus);
715 mOkButton->setFixedSize(mOkButton->sizeHint());
716 connect(mOkButton, SIGNAL(clicked()), SLOT(slotOk()));
717 grid->addWidget(mOkButton, 0, gridIndex++, Qt::AlignHCenter);
718 mOkButton->setWhatsThis(i18nc(
"@info:whatsthis",
"Acknowledge the alarm"));
723 mEditButton =
new PushButton(i18nc(
"@action:button",
"&Edit..."), topWidget);
724 mEditButton->setFocusPolicy(Qt::ClickFocus);
725 mEditButton->setFixedSize(mEditButton->sizeHint());
726 connect(mEditButton, SIGNAL(clicked()), SLOT(slotEdit()));
727 grid->addWidget(mEditButton, 0, gridIndex++, Qt::AlignHCenter);
728 mEditButton->setWhatsThis(i18nc(
"@info:whatsthis",
"Edit the alarm."));
732 mDeferButton =
new PushButton(i18nc(
"@action:button",
"&Defer..."), topWidget);
733 mDeferButton->setFocusPolicy(Qt::ClickFocus);
734 mDeferButton->setFixedSize(mDeferButton->sizeHint());
735 connect(mDeferButton, SIGNAL(clicked()), SLOT(slotDefer()));
736 grid->addWidget(mDeferButton, 0, gridIndex++, Qt::AlignHCenter);
737 mDeferButton->setWhatsThis(i18nc(
"@info:whatsthis",
"<para>Defer the alarm until later.</para>"
738 "<para>You will be prompted to specify when the alarm should be redisplayed.</para>"));
741 mDeferButton->hide();
743 setDeferralLimit(mEvent);
745 if (!mAudioFile.isEmpty() && (mVolume || mFadeVolume > 0))
748 QPixmap pixmap = MainBarIcon(QLatin1String(
"media-playback-stop"));
750 mSilenceButton->setIcon(KIcon(pixmap));
751 grid->addWidget(mSilenceButton, 0, gridIndex++, Qt::AlignHCenter);
752 mSilenceButton->setToolTip(i18nc(
"@info:tooltip",
"Stop sound"));
753 mSilenceButton->setWhatsThis(i18nc(
"@info:whatsthis",
"Stop playing the sound"));
755 mSilenceButton->setEnabled(
false);
758 KIconLoader iconLoader;
759 if (mKMailSerialNumber)
762 QPixmap pixmap = iconLoader.loadIcon(QLatin1String(
"internet-mail"), KIconLoader::MainToolbar);
764 mKMailButton->setIcon(KIcon(pixmap));
765 connect(mKMailButton, SIGNAL(clicked()), SLOT(slotShowKMailMessage()));
766 grid->addWidget(mKMailButton, 0, gridIndex++, Qt::AlignHCenter);
767 mKMailButton->setToolTip(i18nc(
"@info:tooltip Locate this email in KMail",
"Locate in <application>KMail</application>"));
768 mKMailButton->setWhatsThis(i18nc(
"@info:whatsthis",
"Locate and highlight this email in <application>KMail</application>"));
772 QPixmap pixmap = iconLoader.loadIcon(KGlobal::mainComponent().aboutData()->appName(), KIconLoader::MainToolbar);
774 mKAlarmButton->setIcon(KIcon(pixmap));
775 connect(mKAlarmButton, SIGNAL(clicked()), SLOT(displayMainWindow()));
776 grid->addWidget(mKAlarmButton, 0, gridIndex++, Qt::AlignHCenter);
777 mKAlarmButton->setToolTip(i18nc(
"@info:tooltip",
"Activate <application>KAlarm</application>"));
778 mKAlarmButton->setWhatsThis(i18nc(
"@info:whatsthis",
"Activate <application>KAlarm</application>"));
780 int butsize = mKAlarmButton->sizeHint().height();
782 butsize = qMax(butsize, mSilenceButton->sizeHint().height());
784 butsize = qMax(butsize, mKMailButton->sizeHint().height());
785 mKAlarmButton->setFixedSize(butsize, butsize);
787 mSilenceButton->setFixedSize(butsize, butsize);
789 mKMailButton->setFixedSize(butsize, butsize);
793 mOkButton->setEnabled(
false);
794 if (mDeferButton->isVisible())
795 mDeferButton->setEnabled(
false);
797 mEditButton->setEnabled(
false);
799 mKMailButton->setEnabled(
false);
800 mKAlarmButton->setEnabled(
false);
802 topLayout->activate();
803 setMinimumSize(QSize(grid->sizeHint().width() + 2*KDialog::marginHint(),
sizeHint().height()));
804 bool modal = !(windowFlags() & Qt::X11BypassWindowManagerHint);
805 unsigned long wstate = (modal ? NET::Modal : 0) | NET::Sticky | NET::StaysOnTop;
807 KWindowSystem::setState(winid, wstate);
808 KWindowSystem::setOnAllDesktops(winid,
true);
818 int count = mWindowList.count();
819 if (excludeAlwaysHidden)
823 if (win->mAlwaysHide)
832 return mDeferButton && mDeferButton->isVisible();
843 mDeferButton->show();
844 setDeferralLimit(mEvent);
856 mDateTime = alarm.dateTime(
true);
857 mNoPostAction =
false;
858 mAlarmType = alarm.type();
859 if (event.autoClose())
860 mCloseTime = alarm.dateTime().effectiveKDateTime().toUtc().dateTime().addSecs(event.lateCancel() * 60);
861 setCaption(i18nc(
"@title:window",
"Message"));
862 mTimeLabel->setText(dateTimeToDisplay());
864 mRemainingText->hide();
868 centralWidget()->layout()->activate();
869 setMinimumHeight(
sizeHint().height());
881 mDateTime = (alarm.type() & KAAlarm::REMINDER_ALARM) ? event.mainDateTime(
true) : alarm.dateTime(
true);
882 if (mDateTime.isValid())
884 mTimeLabel->setText(dateTimeToDisplay());
892 QString MessageWin::dateTimeToDisplay()
895 if (mDateTime.isValid())
897 if (mDateTime.isDateOnly())
898 tm = KGlobal::locale()->formatDate(mDateTime.date(), KLocale::ShortDate);
901 bool showZone =
false;
902 if (mDateTime.timeType() == KDateTime::UTC
903 || (mDateTime.timeType() == KDateTime::TimeZone && !mDateTime.isLocalZone()))
909 QString tz = mDateTime.kDateTime().toString(QString::fromLatin1(
"%Z"));
910 KDateTime local = mDateTime.kDateTime();
911 local.setTimeSpec(KDateTime::Spec::LocalZone());
912 showZone = (local.toString(QString::fromLatin1(
"%Z")) != tz);
914 tm = KGlobal::locale()->formatDateTime(mDateTime.kDateTime(), KLocale::ShortDate, KLocale::DateTimeFormatOptions(showZone ? KLocale::TimeZone : 0));
924 void MessageWin::setRemainingTextDay()
927 int days = KDateTime::currentLocalDate().daysTo(mDateTime.date());
928 if (days <= 0 && !mDateTime.isDateOnly())
932 setRemainingTextMinute();
938 text = i18nc(
"@info",
"Today");
940 text = i18ncp(
"@info",
"Tomorrow",
"in %1 days' time", days);
942 text = i18ncp(
"@info",
"in 1 week's time",
"in %1 weeks' time", days/7);
944 mRemainingText->setText(text);
951 void MessageWin::setRemainingTextMinute()
954 int mins = (KDateTime::currentUtcDateTime().secsTo(mDateTime.effectiveKDateTime()) + 59) / 60;
956 text = i18ncp(
"@info",
"in 1 minute's time",
"in %1 minutes' time", (mins > 0 ? mins : 0));
957 else if (mins % 60 == 0)
958 text = i18ncp(
"@info",
"in 1 hour's time",
"in %1 hours' time", mins/60);
961 QString hourText = i18ncp(
"@item:intext inserted into 'in ... %1 minute's time' below",
"1 hour",
"%1 hours", mins/60);
962 text = i18ncp(
"@info '%2' is the previous message '1 hour'/'%1 hours'",
"in %2 1 minute's time",
"in %2 %1 minutes' time", mins%60, hourText);
964 mRemainingText->setText(text);
973 QByteArray data = proc->readAll();
978 if (mCommandText->newLine())
979 mCommandText->append(QLatin1String(
"\n"));
980 int nl = data.endsWith(
'\n') ? 1 : 0;
981 mCommandText->setNewLine(nl);
982 mCommandText->insertPlainText(QString::fromLocal8Bit(data.data(), data.length() - nl));
993 if (mShown && !mErrorWindow && !mAlwaysHide)
996 config.writeEntry(
"EventID", mEventId.eventId());
997 config.writeEntry(
"EventItemID", mEventItemId);
999 config.writeEntry(
"EventID", mEventId);
1001 config.writeEntry(
"AlarmType", static_cast<int>(mAlarmType));
1002 if (mAlarmType == KAAlarm::INVALID_ALARM)
1003 kError() <<
"Invalid alarm: id=" << mEventId <<
", alarm count=" << mEvent.alarmCount();
1004 config.writeEntry(
"Message", mMessage);
1005 config.writeEntry(
"Type", static_cast<int>(mAction));
1006 config.writeEntry(
"Font", mFont);
1007 config.writeEntry(
"BgColour", mBgColour);
1008 config.writeEntry(
"FgColour", mFgColour);
1009 config.writeEntry(
"ConfirmAck", mConfirmAck);
1010 if (mDateTime.isValid())
1013 config.writeEntry(
"Time", mDateTime.effectiveDateTime());
1014 config.writeEntry(
"DateOnly", mDateTime.isDateOnly());
1016 if (mDateTime.isUtc())
1017 zone = QLatin1String(
"UTC");
1020 KTimeZone tz = mDateTime.timeZone();
1024 config.writeEntry(
"TimeZone", zone);
1026 if (mCloseTime.isValid())
1027 config.writeEntry(
"Expiry", mCloseTime);
1028 if (mAudioRepeatPause >= 0 && mSilenceButton && mSilenceButton->isEnabled())
1031 config.writePathEntry(
"AudioFile", mAudioFile);
1032 config.writeEntry(
"Volume", static_cast<int>(mVolume * 100));
1033 config.writeEntry(
"AudioPause", mAudioRepeatPause);
1035 config.writeEntry(
"Speak", mSpeak);
1036 config.writeEntry(
"Height", height());
1037 config.writeEntry(
"DeferMins", mDefaultDeferMinutes);
1038 config.writeEntry(
"NoDefer", mNoDefer);
1039 config.writeEntry(
"NoPostAction", mNoPostAction);
1040 config.writeEntry(
"KMailSerial", static_cast<qulonglong>(mKMailSerialNumber));
1041 config.writeEntry(
"CmdErr", static_cast<int>(mCommandError));
1042 config.writeEntry(
"DontShowAgain", mDontShowAgain);
1045 config.writeEntry(
"Invalid",
true);
1055 mInvalid = config.readEntry(
"Invalid",
false);
1057 mEventItemId = config.readEntry(
"EventItemID", Akonadi::Item::Id(-1));
1059 mEventId =
EventId(mCollection.id(), config.readEntry(
"EventID"));
1061 mEventId = config.readEntry(
"EventID");
1063 mAlarmType =
static_cast<KAAlarm::Type
>(config.readEntry(
"AlarmType", 0));
1064 if (mAlarmType == KAAlarm::INVALID_ALARM)
1067 kError() <<
"Invalid alarm: id=" << mEventId;
1069 mMessage = config.readEntry(
"Message");
1070 mAction =
static_cast<KAEvent::SubAction
>(config.readEntry(
"Type", 0));
1071 mFont = config.readEntry(
"Font", QFont());
1072 mBgColour = config.readEntry(
"BgColour", QColor(Qt::white));
1073 mFgColour = config.readEntry(
"FgColour", QColor(Qt::black));
1074 mConfirmAck = config.readEntry(
"ConfirmAck",
false);
1075 QDateTime invalidDateTime;
1076 QDateTime dt = config.readEntry(
"Time", invalidDateTime);
1077 QString zone = config.readEntry(
"TimeZone");
1079 mDateTime = KDateTime(dt, KDateTime::ClockTime);
1080 else if (zone == QLatin1String(
"UTC"))
1082 dt.setTimeSpec(Qt::UTC);
1083 mDateTime = KDateTime(dt, KDateTime::UTC);
1087 KTimeZone tz = KSystemTimeZones::zone(zone);
1088 mDateTime = KDateTime(dt, (tz.isValid() ? tz : KSystemTimeZones::local()));
1090 bool dateOnly = config.readEntry(
"DateOnly",
false);
1092 mDateTime.setDateOnly(
true);
1093 mCloseTime = config.readEntry(
"Expiry", invalidDateTime);
1094 mCloseTime.setTimeSpec(Qt::UTC);
1095 mAudioFile = config.readPathEntry(
"AudioFile", QString());
1096 mVolume =
static_cast<float>(config.readEntry(
"Volume", 0)) / 100;
1099 if (!mAudioFile.isEmpty())
1100 mAudioRepeatPause = config.readEntry(
"AudioPause", 0);
1102 mSpeak = config.readEntry(
"Speak",
false);
1103 mRestoreHeight = config.readEntry(
"Height", 0);
1104 mDefaultDeferMinutes = config.readEntry(
"DeferMins", 0);
1105 mNoDefer = config.readEntry(
"NoDefer",
false);
1106 mNoPostAction = config.readEntry(
"NoPostAction",
true);
1107 mKMailSerialNumber =
static_cast<unsigned long>(config.readEntry(
"KMailSerial", QVariant(QVariant::ULongLong)).toULongLong());
1108 mCommandError = KAEvent::CmdErrType(config.readEntry(
"CmdErr", static_cast<int>(KAEvent::CMD_NO_ERROR)));
1109 mDontShowAgain = config.readEntry(
"DontShowAgain", QString());
1112 mCollection = Akonadi::Collection();
1116 kDebug() << mEventId;
1117 if (mAlarmType != KAAlarm::INVALID_ALARM)
1135 retrieveEvent(mEvent, mCollection, mShowEdit, mNoDefer);
1137 retrieveEvent(mEvent, mResource, mShowEdit, mNoDefer);
1139 mNoDefer = !mNoDefer;
1159 Akonadi::Collection collection;
1161 AlarmResource* resource;
1164 for (
int i = 0, end = events.count(); i < end; ++i)
1168 reinstateFromDisplaying(events[i], event, collection, showEdit, showDefer);
1171 reinstateFromDisplaying(events[i], event, resource, showEdit, showDefer);
1176 KAAlarm alarm =
event.convertDisplayingAlarm();
1177 if (alarm.type() == KAAlarm::INVALID_ALARM)
1179 kError() <<
"Invalid alarm: id=" <<
event.id();
1182 kDebug() <<
event.id();
1183 bool login = alarm.repeatAtLogin();
1187 win->mCollection = collection;
1190 win->mResource = resource;
1191 bool rw = resource && resource->writable();
1193 win->mShowEdit = rw ? showEdit :
false;
1194 win->mNoDefer = (rw && !login) ? !showDefer :
true;
1207 bool MessageWin::retrieveEvent(KAEvent& event, Akonadi::Collection& resource,
bool& showEdit,
bool& showDefer)
1209 bool MessageWin::retrieveEvent(KAEvent& event, AlarmResource*& resource,
bool& showEdit,
bool& showDefer)
1217 if (!reinstateFromDisplaying(kcalEvent, event, resource, showEdit, showDefer))
1224 if (archiveCol.isValid())
1233 event.setCategory(CalEvent::ACTIVE);
1235 if (mEventId.eventId() !=
event.id())
1236 kError() <<
"Wrong event ID";
1237 event.setEventId(mEventId.eventId());
1238 resource = Akonadi::Collection();
1240 if (mEventId != event.id())
1241 kError() <<
"Wrong event ID";
1242 event.setEventId(mEventId);
1247 kDebug() <<
event.id() <<
": success";
1257 bool MessageWin::reinstateFromDisplaying(
const Event::Ptr& kcalEvent, KAEvent& event, Akonadi::Collection& collection,
bool& showEdit,
bool& showDefer)
1259 bool MessageWin::reinstateFromDisplaying(
const Event* kcalEvent, KAEvent& event, AlarmResource*& resource,
bool& showEdit,
bool& showDefer)
1265 Akonadi::Collection::Id collectionId;
1266 event.reinstateFromDisplaying(kcalEvent, collectionId, showEdit, showDefer);
1270 event.reinstateFromDisplaying(kcalEvent, resourceID, showEdit, showDefer);
1271 resource = AlarmResources::instance()->resourceWithId(resourceID);
1272 if (resource && !resource->isOpen())
1275 kDebug() <<
event.id() <<
": success";
1284 void MessageWin::alarmShowing(KAEvent& event)
1286 kDebug() <<
event.id() <<
"," << KAAlarm::debugType(mAlarmType);
1291 kError() <<
"Event ID not found:" <<
event.id();
1295 KAAlarm alarm =
event.alarm(mAlarmType);
1296 if (!alarm.isValid())
1298 kError() <<
"Alarm type not found:" <<
event.id() <<
":" << mAlarmType;
1307 dispEvent.setDisplaying(event, mAlarmType, collection.id(),
1308 mDateTime.effectiveKDateTime(), mShowEdit, !mNoDefer);
1310 KAEvent* dispEvent =
new KAEvent;
1311 AlarmResource* resource = AlarmResources::instance()->resource(kcalEvent);
1312 dispEvent->setDisplaying(event, mAlarmType, (resource ? resource->identifier() : QString()),
1313 mDateTime.effectiveKDateTime(), mShowEdit, !mNoDefer);
1319 cal->deleteDisplayEvent(dispEvent.id());
1347 if (scatter == isSpread(desk.topLeft()))
1354 int x = desk.left();
1357 for (
int errmsgs = 0; errmsgs < 2; ++errmsgs)
1361 for (
int i = 0, end = mWindowList.count(); i < end; ++i)
1364 if ((!errmsgs && w->mErrorWindow)
1365 || (errmsgs && !w->mErrorWindow))
1367 QSize sz = w->frameGeometry().size();
1368 if (x + sz.width() > desk.right())
1374 if (y + sz.height() > desk.bottom())
1376 ytmp = desk.bottom() - sz.height();
1377 if (ytmp < desk.top())
1382 if (ytmp + sz.height() > ynext)
1383 ynext = ytmp + sz.height();
1390 for (
int i = 0, end = mWindowList.count(); i < end; ++i)
1391 mWindowList[i]->move(desk.topLeft());
1400 bool MessageWin::isSpread(
const QPoint& topLeft)
1402 for (
int i = 0, end = mWindowList.count(); i < end; ++i)
1404 if (mWindowList[i]->pos() != topLeft)
1420 if (!eventId.isEmpty())
1422 for (
int i = 0, end = mWindowList.count(); i < end; ++i)
1425 if (w->mEventId == eventId && !w->mErrorWindow)
1435 void MessageWin::playAudio()
1440 QApplication::beep();
1441 KNotification::beep();
1443 if (!mAudioFile.isEmpty())
1445 if (!mVolume && mFadeVolume <= 0)
1453 QTimer::singleShot(0,
this, SLOT(slotSpeak()));
1461 void MessageWin::slotSpeak()
1474 if (!kspeech->say(mMessage, 0))
1476 kDebug() <<
"SayMessage() D-Bus error";
1491 void MessageWin::startAudio()
1497 connect(mAudioThread, SIGNAL(destroyed(
QObject*)), SLOT(audioTerminating()));
1501 kDebug() << QThread::currentThread();
1502 mAudioThread =
new AudioThread(
this, mAudioFile, mVolume, mFadeVolume, mFadeSeconds, mAudioRepeatPause);
1503 connect(mAudioThread, SIGNAL(readyToPlay()), SLOT(playReady()));
1504 connect(mAudioThread, SIGNAL(finished()), SLOT(playFinished()));
1506 connect(mSilenceButton, SIGNAL(clicked()), mAudioThread, SLOT(quit()));
1510 mAudioThread->start();
1519 return mAudioThread;
1529 mAudioThread->stop(wait);
1536 void MessageWin::audioTerminating()
1538 QTimer::singleShot(0,
this, SLOT(startAudio()));
1544 void MessageWin::playReady()
1547 mSilenceButton->setEnabled(
true);
1553 void MessageWin::playFinished()
1556 mSilenceButton->setEnabled(
false);
1559 QString errmsg = mAudioThread->error();
1566 delete mAudioThread.data();
1578 mFadeVolume(fadeVolume),
1579 mFadeSeconds(fadeSeconds),
1580 mRepeatPause(repeatPause),
1584 kError() <<
"mAudioOwner already set";
1596 delete mAudioObject;
1602 QTimer::singleShot(0,
theApp(), SLOT(notifyAudioStopped()));
1633 kDebug() << QThread::currentThread() << mFile;
1634 QString audioFile = mFile;
1635 mFile = KAlarm::pathOrUrl(mFile);
1636 Phonon::MediaSource source(audioFile);
1637 if (source.type() == Phonon::MediaSource::Invalid)
1639 mError = i18nc(
"@info",
"Cannot open audio file: <filename>%1</filename>", audioFile);
1641 kError() <<
"Open failure:" << audioFile;
1644 mAudioObject =
new Phonon::MediaObject();
1645 mAudioObject->setCurrentSource(source);
1646 mAudioObject->setTransitionTime(100);
1647 Phonon::AudioOutput* output =
new Phonon::AudioOutput(Phonon::NotificationCategory, mAudioObject);
1648 mPath = Phonon::createPath(mAudioObject, output);
1649 if (mVolume >= 0 || mFadeVolume >= 0)
1651 float vol = (mVolume >= 0) ? mVolume : output->volume();
1652 float maxvol = qMax(vol, mFadeVolume);
1653 output->setVolume(maxvol);
1654 if (mFadeVolume >= 0 && mFadeSeconds > 0)
1656 Phonon::VolumeFaderEffect* fader =
new Phonon::VolumeFaderEffect(mAudioObject);
1657 fader->setVolume(mFadeVolume / maxvol);
1658 fader->fadeTo(mVolume / maxvol, mFadeSeconds * 1000);
1659 mPath.insertEffect(fader);
1662 connect(mAudioObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), SLOT(playStateChanged(Phonon::State)), Qt::DirectConnection);
1663 connect(mAudioObject, SIGNAL(finished()), SLOT(checkAudioPlay()), Qt::DirectConnection);
1664 mPlayedOnce =
false;
1673 connect(
this, SIGNAL(finished()),
this, SLOT(deleteLater()));
1684 void AudioThread::checkAudioPlay()
1699 if (mRepeatPause < 0)
1706 if (mRepeatPause > 0)
1710 QTimer::singleShot(mRepeatPause * 1000,
this, SLOT(checkAudioPlay()));
1719 kDebug() <<
"start";
1720 mAudioObject->play();
1728 void AudioThread::playStateChanged(Phonon::State newState)
1730 if (newState == Phonon::ErrorState)
1732 QMutexLocker locker(&mMutex);
1733 QString err = mAudioObject->errorString();
1736 kError() <<
"Play failure:" << mFile <<
":" << err;
1737 mError = i18nc(
"@info",
"<para>Error playing audio file: <filename>%1</filename></para><para>%2</para>", mFile, err);
1747 void AudioThread::stopPlay()
1752 mAudioObject->stop();
1754 for (
int i = 0; i < effects.count(); ++i)
1756 mPath.removeEffect(effects[i]);
1759 delete mAudioObject;
1768 QMutexLocker locker(&mMutex);
1790 mAlarmType = alarm.type();
1800 if (mDeferButton->isVisible())
1802 mDeferButton->setEnabled(
true);
1803 setDeferralLimit(*event);
1806 alarmShowing(*event);
1818 if (mCloseTime.isValid())
1821 int delay = KDateTime::currentUtcDateTime().dateTime().secsTo(mCloseTime);
1824 QTimer::singleShot(delay * 1000,
this, SLOT(close()));
1830 MainWindowBase::show();
1841 case KAEvent::MESSAGE:
1842 desired = MainWindowBase::sizeHint();
1844 case KAEvent::COMMAND:
1848 QSize texthint = mCommandText->sizeHint();
1849 int w = texthint.width() + 2*KDialog::marginHint();
1852 int ypadding = height() - mCommandText->height();
1853 desired = QSize(w, texthint.height() + ypadding);
1858 return MainWindowBase::sizeHint();
1863 QSize frameThickness = frameGeometry().size() - geometry().size();
1864 return desired.boundedTo(desktop - frameThickness);
1874 MainWindowBase::showEvent(se);
1877 if (mErrorWindow || mAlarmType == KAAlarm::INVALID_ALARM)
1890 bool execComplete =
true;
1892 if (mAction == KAEvent::FILE && !mErrorMsgs.count())
1893 KAlarm::readConfigWindowSize(
"FileMessage", s);
1897 QRect frame = frameGeometry();
1904 mPositioning =
true;
1905 move((desk.width() - frame.width())/2, (desk.height() - frame.height())/2);
1906 execComplete =
false;
1921 QPoint cursor = QCursor::pos();
1922 QRect rect = geometry();
1924 QRect button(mOkButton->mapToParent(QPoint(0, 0)), mOkButton->mapToParent(mOkButton->rect().bottomRight()));
1925 int buttonLeft = button.left() + rect.left() - frame.left();
1926 int buttonRight = width() - button.right() + frame.right() - rect.right();
1927 int buttonTop = button.top() + rect.top() - frame.top();
1928 int buttonBottom = height() - button.bottom() + frame.bottom() - rect.bottom();
1930 int centrex = (desk.width() + buttonLeft - buttonRight) / 2;
1931 int centrey = (desk.height() + buttonTop - buttonBottom) / 2;
1932 int x = (cursor.x() < centrex) ? desk.right() - frame.width() : desk.left();
1933 int y = (cursor.y() < centrey) ? desk.bottom() - frame.height() : desk.top();
1937 QRect buttons = mOkButton->geometry().unite(mKAlarmButton->geometry());
1938 buttons.translate(rect.left() + x - frame.left(), rect.top() + y - frame.top());
1940 if ((abs(cursor.x() - buttons.left()) < minDistance
1941 || abs(cursor.x() - buttons.right()) < minDistance)
1942 && (abs(cursor.y() - buttons.top()) < minDistance
1943 || abs(cursor.y() - buttons.bottom()) < minDistance))
1946 if (x != frame.left() || y != frame.top())
1948 mPositioning =
true;
1950 execComplete =
false;
1958 QTimer::singleShot(0,
this, SLOT(frameDrawn()));
1968 MainWindowBase::moveEvent(e);
1973 mPositioning =
false;
1983 void MessageWin::frameDrawn()
1985 if (!mErrorWindow && mAction == KAEvent::MESSAGE)
1988 if (width() > s.width() || height() > s.height())
1998 void MessageWin::displayComplete()
2001 if (mRescheduleEvent)
2002 alarmShowing(mEvent);
2007 if (mButtonDelay > 0)
2008 QTimer::singleShot(mButtonDelay,
this, SLOT(enableButtons()));
2017 void MessageWin::enableButtons()
2019 mOkButton->setEnabled(
true);
2020 mKAlarmButton->setEnabled(
true);
2021 if (mDeferButton->isVisible() && !mDisableDeferral)
2022 mDeferButton->setEnabled(
true);
2024 mEditButton->setEnabled(
true);
2026 mKMailButton->setEnabled(
true);
2037 if (mRestoreHeight != re->size().height())
2039 QSize size = re->size();
2040 size.setHeight(mRestoreHeight);
2043 else if (isVisible())
2048 if (mShown && mAction == KAEvent::FILE && !mErrorMsgs.count())
2049 KAlarm::writeConfigWindowSize(
"FileMessage", re->size());
2050 MainWindowBase::resizeEvent(re);
2061 if (!mErrorWindow && !
theApp()->sessionClosingDown())
2063 if (mConfirmAck && !mNoCloseConfirm)
2067 i18nc(
"@action:button",
"Acknowledge Alarm"), KGuiItem(i18nc(
"@action:button",
"Acknowledge")), KStandardGuiItem::cancel())
2068 != KMessageBox::Yes)
2074 if (!mEventId.isEmpty())
2078 KAlarm::deleteDisplayEvent(CalEvent::uid(mEventId.eventId(), CalEvent::DISPLAYING));
2080 KAlarm::deleteDisplayEvent(CalEvent::uid(mEventId, CalEvent::DISPLAYING));
2090 void MessageWin::slotOk()
2092 if (mDontShowAgainCheck && mDontShowAgainCheck->isChecked())
2093 KAlarm::setDontShowErrors(mEventId, mDontShowAgain);
2097 #ifdef KMAIL_SUPPORTED
2102 void MessageWin::slotShowKMailMessage()
2105 if (!mKMailSerialNumber)
2107 QString err = KAlarm::runKMail(
false);
2113 org::kde::kmail::kmail kmail(KMAIL_DBUS_SERVICE, KMAIL_DBUS_PATH, QDBusConnection::sessionBus());
2114 QDBusReply<bool> reply = kmail.showMail((qulonglong)mKMailSerialNumber, QString());
2115 if (!reply.isValid())
2116 kError() <<
"kmail D-Bus call failed:" << reply.error().message();
2117 else if (!reply.value())
2118 KAMessageBox::sorry(
this, i18nc(
"@info",
"Unable to locate this email in <application>KMail</application>"));
2132 void MessageWin::slotEdit()
2137 KWindowSystem::setMainWindow(mEditDlg, winId());
2138 KWindowSystem::setOnAllDesktops(mEditDlg->winId(),
false);
2139 setButtonsReadOnly(
true);
2140 connect(mEditDlg, SIGNAL(accepted()), SLOT(editCloseOk()));
2141 connect(mEditDlg, SIGNAL(rejected()), SLOT(editCloseCancel()));
2142 connect(mEditDlg, SIGNAL(destroyed(
QObject*)), SLOT(editCloseCancel()));
2143 connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), SLOT(activeWindowChanged(WId)));
2145 mainWin->
editAlarm(mEditDlg, mOriginalEvent);
2147 mainWin->
editAlarm(mEditDlg, mOriginalEvent, mResource);
2155 void MessageWin::editCloseOk()
2158 mNoCloseConfirm =
true;
2166 void MessageWin::editCloseCancel()
2169 setButtonsReadOnly(
false);
2177 void MessageWin::activeWindowChanged(WId win)
2179 if (mEditDlg && win == winId())
2180 KWindowSystem::activateWindow(mEditDlg->winId());
2186 void MessageWin::setButtonsReadOnly(
bool ro)
2201 void MessageWin::setDeferralLimit(
const KAEvent& event)
2203 mDeferLimit =
event.deferralLimit().effectiveKDateTime().toUtc().dateTime();
2205 mDisableDeferral =
false;
2206 checkDeferralLimit();
2218 void MessageWin::checkDeferralLimit()
2220 if (!mDeferButton->isEnabled() || !mDeferLimit.isValid())
2222 int n = KDateTime::currentLocalDate().daysTo(KDateTime(mDeferLimit, KDateTime::LocalZone).
date());
2229 n = KDateTime::currentUtcDateTime().dateTime().secsTo(mDeferLimit);
2232 QTimer::singleShot(n * 1000,
this, SLOT(checkDeferralLimit()));
2236 mDeferButton->setEnabled(
false);
2237 mDisableDeferral =
true;
2244 void MessageWin::slotDefer()
2247 mDeferDlg->setObjectName(QLatin1String(
"DeferDlg"));
2252 if (mDeferDlg->exec() == QDialog::Accepted)
2262 kDebug() <<
"Deferring event" << mEventId;
2263 KAEvent newev(*event);
2264 newev.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM),
true);
2265 newev.setDeferDefaultMinutes(delayMins);
2266 KAlarm::updateEvent(newev, mDeferDlg,
true);
2267 if (newev.deferred())
2268 mNoPostAction =
true;
2274 Akonadi::Collection collection;
2276 AlarmResource* resource = 0;
2281 if (!retrieveEvent(event, collection, showEdit, showDefer))
2283 if (!retrieveEvent(event, resource, showEdit, showDefer))
2288 KAMessageBox::error(
this, i18nc(
"@info",
"<para>Cannot defer alarm:</para><para>Alarm not found.</para>"));
2292 mDeferButton->setEnabled(
false);
2293 mEditButton->setEnabled(
false);
2296 kDebug() <<
"Deferring retrieved event" << mEventId;
2297 event.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM),
true);
2298 event.setDeferDefaultMinutes(delayMins);
2299 event.setCommandError(mCommandError);
2303 KAlarm::addEvent(event, &collection, mDeferDlg, KAlarm::USE_EVENT_ID);
2305 KAlarm::addEvent(event, resource, mDeferDlg, KAlarm::USE_EVENT_ID);
2307 if (event.deferred())
2308 mNoPostAction =
true;
2311 event.setCategory(CalEvent::ARCHIVED);
2312 KAlarm::deleteEvent(event,
false);
2314 if (
theApp()->wantShowInSystemTray())
2320 mNoCloseConfirm =
true;
2333 void MessageWin::displayMainWindow()
2336 KAlarm::displayMainWindowSelected(mEventItemId);
2338 KAlarm::displayMainWindowSelected(mEventId);
2347 bool MessageWin::haveErrorMessage(
unsigned msg)
const
2349 if (!mErrorMessages.contains(mEventId))
2350 mErrorMessages.insert(mEventId, 0);
2351 bool result = (mErrorMessages[mEventId] & msg);
2352 mErrorMessages[mEventId] |= msg;
2356 void MessageWin::clearErrorMessage(
unsigned msg)
const
2358 if (mErrorMessages.contains(mEventId))
2360 if (mErrorMessages[mEventId] == msg)
2361 mErrorMessages.remove(mEventId);
2363 mErrorMessages[mEventId] &= ~msg;
2378 bool MessageWin::getWorkAreaAndModal()
2383 QDesktopWidget* desktop = qApp->desktop();
2384 int numScreens = desktop->numScreens();
2391 if (desktop->isVirtualDesktop())
2395 QVector<FullScreenType> screenTypes(numScreens);
2396 QVector<QRect> screenRects(numScreens);
2397 for (
int s = 0; s < numScreens; ++s)
2398 screenRects[s] = desktop->screenGeometry(s);
2399 FullScreenType full = findFullScreenWindows(screenRects, screenTypes);
2400 if (full == NoFullScreen || screenTypes[mScreenNumber] == NoFullScreen)
2402 for (
int s = 0; s < numScreens; ++s)
2404 if (screenTypes[s] == NoFullScreen)
2414 for (
int s = 0; s < numScreens; ++s)
2416 if (screenTypes[s] == FullScreen)
2426 int inactiveScreen = -1;
2427 FullScreenType full = haveFullScreenWindow(mScreenNumber);
2428 kDebug()<<
"full="<<full<<
", screen="<<mScreenNumber;
2429 if (full == NoFullScreen)
2431 if (full == FullScreen)
2432 inactiveScreen = mScreenNumber;
2433 for (
int s = 0; s < numScreens; ++s)
2435 if (s != mScreenNumber)
2437 full = haveFullScreenWindow(s);
2438 if (full == NoFullScreen)
2444 if (full == FullScreen && inactiveScreen < 0)
2448 if (inactiveScreen >= 0)
2452 mScreenNumber = inactiveScreen;
2461 WId activeId = KWindowSystem::activeWindow();
2462 KWindowInfo wi = KWindowSystem::windowInfo(activeId, NET::WMState);
2463 if (wi.valid() && wi.hasState(NET::FullScreen))
2474 FullScreenType haveFullScreenWindow(
int screen)
2476 FullScreenType type = NoFullScreen;
2477 Display* display = QX11Info::display();
2478 NETRootInfo rootInfo(display, NET::ClientList | NET::ActiveWindow, screen);
2479 Window rootWindow = rootInfo.rootWindow();
2480 Window activeWindow = rootInfo.activeWindow();
2481 const Window* windows = rootInfo.clientList();
2482 int windowCount = rootInfo.clientListCount();
2483 kDebug()<<
"Screen"<<screen<<
": Window count="<<windowCount<<
", active="<<activeWindow<<
", geom="<<qApp->desktop()->screenGeometry(screen);
2486 for (
int w = 0; w < windowCount; ++w)
2488 NETWinInfo winInfo(display, windows[w], rootWindow, NET::WMState|NET::WMGeometry);
2489 winInfo.kdeGeometry(frame, geom);
2490 QRect fr(frame.pos.x, frame.pos.y, frame.size.width, frame.size.height);
2491 QRect gm(geom.pos.x, geom.pos.y, geom.size.width, geom.size.height);
2492 if (winInfo.state() & NET::FullScreen)
2494 kDebug()<<
"Found FULL SCREEN: "<<windows[w]<<
", geom="<<gm<<
", frame="<<fr;
2496 if (windows[w] == activeWindow)
2497 return FullScreenActive;
2508 FullScreenType findFullScreenWindows(
const QVector<QRect>& screenRects, QVector<FullScreenType>& screenTypes)
2510 FullScreenType result = NoFullScreen;
2511 screenTypes.fill(NoFullScreen);
2512 Display* display = QX11Info::display();
2513 NETRootInfo rootInfo(display, NET::ClientList | NET::ActiveWindow, 0);
2514 Window rootWindow = rootInfo.rootWindow();
2515 Window activeWindow = rootInfo.activeWindow();
2516 const Window* windows = rootInfo.clientList();
2517 int windowCount = rootInfo.clientListCount();
2518 kDebug()<<
"Virtual desktops: Window count="<<windowCount<<
", active="<<activeWindow<<
", geom="<<qApp->desktop()->screenGeometry(0);
2521 for (
int w = 0; w < windowCount; ++w)
2523 NETWinInfo winInfo(display, windows[w], rootWindow, NET::WMState | NET::WMGeometry);
2524 if (winInfo.state() & NET::FullScreen)
2527 bool active = (windows[w] == activeWindow);
2528 winInfo.kdeGeometry(netframe, netgeom);
2529 QRect winRect(netgeom.pos.x, netgeom.pos.y, netgeom.size.width, netgeom.size.height);
2530 kDebug()<<
"Found FULL SCREEN: "<<windows[w]<<
", geom="<<winRect;
2531 for (
int s = 0, count = screenRects.count(); s < count; ++s)
2533 if (screenRects[s].contains(winRect))
2535 kDebug()<<
"FULL SCREEN on screen"<<s<<
", active="<<active;
2537 screenTypes[s] = result = FullScreenActive;
2540 if (screenTypes[s] == NoFullScreen)
2541 screenTypes[s] = FullScreen;
2542 if (result == NoFullScreen)
2543 result = FullScreen;
static int defaultDeferTime()
Get Default defer time interval.
static int messageButtonDelay()
Get Delay before message window buttons are enabled.
virtual void resizeEvent(QResizeEvent *)
void rescheduleAlarm(KAEvent &e, const KAAlarm &a)
static Akonadi::Collection getStandard(CalEvent::Type, bool useDefault=false)
Return the standard collection for a specified mime type.
virtual void moveEvent(QMoveEvent *)
bool deleteEvent(const QString &eventID, bool save=false)
static int isWritableEnabled(const Akonadi::Collection &, CalEvent::Type)
Return whether a collection is both enabled and fully writable for a given alarm type, i.e.
static bool isAudioPlaying()
AudioThread(MessageWin *parent, const QString &audioFile, float volume, float fadeVolume, int fadeSeconds, int repeatPause)
static void connect(QObject *receiver, const char *member)
bool eventReadOnly(const QString &uniqueID) const
virtual QByteArray text(quint32 serialNumber) const =0
static bool spread(bool scatter)
KCal::Event * kcalEvent(const QString &uniqueId)
The MainWindowBase class is a base class for KAlarm's main window and message window.
static AlarmCalendar * resources()
static void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Options(Notify|WindowModal))
bool addEvent(KAEvent *, QWidget *promptParent=0, bool useEventID=false, AlarmResource *=0, bool noPrompt=false, bool *cancelled=0)
static const Qt::WidgetAttribute WidgetFlags
void setDeferMinutes(int mins)
virtual void closeEvent(QCloseEvent *)
AlarmResource * resourceForEvent(const QString &eventID) const
Akonadi::Collection collectionById(Akonadi::Collection::Id) const
the KAlarm application object
void editAlarm(EditAlarmDlg *, const KAEvent &, AlarmResource *)
MessageWin: A window to display an alarm or error message.
static const Qt::WindowFlags WFLAGS2
virtual void saveProperties(KConfigGroup &)
ShellProcess * execCommandAlarm(const KAEvent &, const KAAlarm &, const QObject *receiver=0, const char *slot=0)
static KTimeZone timeZone(bool reload=false)
void notifyAudioPlaying(bool playing)
static AkonadiModel * instance()
static const int proximityMultiple
static void stopAudio(bool wait=false)
static EditAlarmDlg * create(bool Template, Type, QWidget *parent=0, GetResourceType=RES_PROMPT)
static const Qt::WindowFlags WFLAGS
static void disconnect(QObject *receiver, const char *member=0)
static void connect(QObject *receiver, const char *member)
const DateTime & dateTime()
static void detailedError(QWidget *parent, const QString &text, const QString &details, const QString &caption=QString(), Options options=Options(Notify|WindowModal))
static int instanceCount(bool excludeAlwaysHidden=false)
static void redisplayAlarms()
virtual QSize sizeHint() const
static MessageWin * findEvent(const QString &eventId)
void showDateTime(const KAEvent &, const KAAlarm &)
Unique event identifier for Akonadi.
KCal::Event::List kcalEvents(CalEvent::Type s=CalEvent::EMPTY)
const DateTime & getDateTime() const
void repeat(const KAAlarm &)
static int warningYesNo(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const QString &dontAskAgainName=QString(), Options options=Options(Notify|Dangerous|WindowModal))
static void sorry(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Options(Notify|WindowModal))
void setLimit(const DateTime &)
static void showError(const KAEvent &, const DateTime &alarmDateTime, const QStringList &errmsgs, const QString &dontShowAgain=QString())
static bool modalMessages()
Get Message windows have a title bar and take keyboard focus.
void cancelReminder(const KAEvent &, const KAAlarm &)
static void disconnect(QObject *receiver, const char *member=0)
virtual void readProperties(const KConfigGroup &)
bool displayTrayIcon(bool show, MainWindow *=0)
Provides read and write access to calendar files and resources.
static AlarmCalendar * displayCalendarOpen()
static const int proximityButtonDelay
void stop(bool wait=false)
OrgKdeKSpeechInterface * kspeechInterface(QString &error) const
KAEvent * event(const QString &uniqueId)
static MainWindow * mainMainWindow()
QRect desktopWorkArea(int screen)
virtual void showEvent(QShowEvent *)
Akonadi::Collection collectionForItem(Akonadi::Item::Id) const
virtual void closeEvent(QCloseEvent *)
static AlarmCalendar * displayCalendar()
bool isEmpty() const
Return whether the instance contains any data.
void setSpreadWindowsState(bool spread)
void alarmCompleted(const KAEvent &)
static MessageWin * mAudioOwner