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