00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kalarm.h"
00022
00023 #include <stdlib.h>
00024 #include <string.h>
00025
00026 #include <qfile.h>
00027 #include <qfileinfo.h>
00028 #include <qlayout.h>
00029 #include <qpushbutton.h>
00030 #include <qlabel.h>
00031 #include <qwhatsthis.h>
00032 #include <qtooltip.h>
00033 #include <qdragobject.h>
00034 #include <qtextedit.h>
00035 #include <qtimer.h>
00036
00037 #include <kstandarddirs.h>
00038 #include <kaction.h>
00039 #include <kstdguiitem.h>
00040 #include <kaboutdata.h>
00041 #include <klocale.h>
00042 #include <kconfig.h>
00043 #include <kiconloader.h>
00044 #include <kdialog.h>
00045 #include <ktextbrowser.h>
00046 #include <kglobalsettings.h>
00047 #include <kmimetype.h>
00048 #include <kmessagebox.h>
00049 #include <kwin.h>
00050 #include <kwinmodule.h>
00051 #include <kprocess.h>
00052 #include <kio/netaccess.h>
00053 #include <knotifyclient.h>
00054 #include <kpushbutton.h>
00055 #ifdef WITHOUT_ARTS
00056 #include <kaudioplayer.h>
00057 #else
00058 #include <arts/kartsdispatcher.h>
00059 #include <arts/kartsserver.h>
00060 #include <arts/kplayobjectfactory.h>
00061 #include <arts/kplayobject.h>
00062 #endif
00063 #include <dcopclient.h>
00064 #include <kdebug.h>
00065
00066 #include "alarmcalendar.h"
00067 #include "deferdlg.h"
00068 #include "editdlg.h"
00069 #include "functions.h"
00070 #include "kalarmapp.h"
00071 #include "mainwindow.h"
00072 #include "preferences.h"
00073 #include "synchtimer.h"
00074 #include "messagewin.moc"
00075
00076 using namespace KCal;
00077
00078 #ifndef WITHOUT_ARTS
00079 static const char* KMIX_APP_NAME = "kmix";
00080 static const char* KMIX_DCOP_OBJECT = "Mixer0";
00081 static const char* KMIX_DCOP_WINDOW = "kmix-mainwindow#1";
00082 #endif
00083 static const char* KMAIL_DCOP_OBJECT = "KMailIface";
00084
00085
00086
00087 static const int proximityButtonDelay = 1000;
00088 static const int proximityMultiple = 10;
00089
00090
00091 class MessageText : public QTextEdit
00092 {
00093 public:
00094 MessageText(const QString& text, const QString& context = QString::null, QWidget* parent = 0, const char* name = 0)
00095 : QTextEdit(text, context, parent, name)
00096 {
00097 setReadOnly(true);
00098 setWordWrap(QTextEdit::NoWrap);
00099 }
00100 int scrollBarHeight() const { return horizontalScrollBar()->height(); }
00101 int scrollBarWidth() const { return verticalScrollBar()->width(); }
00102 virtual QSize sizeHint() const { return QSize(contentsWidth() + scrollBarWidth(), contentsHeight() + scrollBarHeight()); }
00103 };
00104
00105
00106 class MWMimeSourceFactory : public QMimeSourceFactory
00107 {
00108 public:
00109 MWMimeSourceFactory(const QString& absPath, KTextBrowser*);
00110 virtual ~MWMimeSourceFactory();
00111 virtual const QMimeSource* data(const QString& abs_name) const;
00112 private:
00113
00114 virtual void setData(const QString&, QMimeSource*) {}
00115 virtual void setExtensionType(const QString&, const char*) {}
00116
00117 QString mTextFile;
00118 QCString mMimeType;
00119 mutable const QMimeSource* mLast;
00120 };
00121
00122
00123
00124 static const Qt::WFlags WFLAGS = Qt::WStyle_StaysOnTop | Qt::WDestructiveClose;
00125
00126
00127 QValueList<MessageWin*> MessageWin::mWindowList;
00128
00129
00130
00131
00132
00133
00134
00135
00136 MessageWin::MessageWin(const KAEvent& event, const KAAlarm& alarm, bool reschedule_event, bool allowDefer)
00137 : MainWindowBase(0, "MessageWin", WFLAGS | Qt::WGroupLeader | Qt::WStyle_ContextHelp
00138 | (Preferences::modalMessages() ? 0 : Qt::WX11BypassWM)),
00139 mMessage(event.cleanText()),
00140 mFont(event.font()),
00141 mBgColour(event.bgColour()),
00142 mFgColour(event.fgColour()),
00143 mDateTime((alarm.type() & KAAlarm::REMINDER_ALARM) ? event.mainDateTime() : alarm.dateTime()),
00144 mEventID(event.id()),
00145 mAudioFile(event.audioFile()),
00146 mVolume(event.soundVolume()),
00147 mFadeVolume(event.fadeVolume()),
00148 mFadeSeconds(QMIN(event.fadeSeconds(), 86400)),
00149 mAlarmType(alarm.type()),
00150 mAction(event.action()),
00151 mKMailSerialNumber(event.kmailSerialNumber()),
00152 mRestoreHeight(0),
00153 mAudioRepeat(event.repeatSound()),
00154 mConfirmAck(event.confirmAck()),
00155 mShowEdit(!mEventID.isEmpty()),
00156 mNoDefer(!allowDefer || alarm.repeatAtLogin()),
00157 mInvalid(false),
00158 mArtsDispatcher(0),
00159 mPlayObject(0),
00160 mOldVolume(-1),
00161 mEvent(event),
00162 mEditButton(0),
00163 mDeferButton(0),
00164 mSilenceButton(0),
00165 mDeferDlg(0),
00166 mWinModule(0),
00167 mFlags(event.flags()),
00168 mLateCancel(event.lateCancel()),
00169 mErrorWindow(false),
00170 mNoPostAction(false),
00171 mRecreating(false),
00172 mBeep(event.beep()),
00173 mSpeak(event.speak()),
00174 mRescheduleEvent(reschedule_event),
00175 mShown(false),
00176 mPositioning(false),
00177 mNoCloseConfirm(false)
00178 {
00179 kdDebug(5950) << "MessageWin::MessageWin(event)" << endl;
00180
00181
00182 setAutoSaveSettings(QString::fromLatin1("MessageWin"), false);
00183 initView();
00184 mWindowList.append(this);
00185 if (event.autoClose())
00186 mCloseTime = alarm.dateTime().dateTime().addSecs(event.lateCancel() * 60);
00187 }
00188
00189
00190
00191
00192 MessageWin::MessageWin(const KAEvent& event, const DateTime& alarmDateTime, const QStringList& errmsgs)
00193 : MainWindowBase(0, "MessageWin", WFLAGS | Qt::WGroupLeader | Qt::WStyle_ContextHelp),
00194 mMessage(event.cleanText()),
00195 mDateTime(alarmDateTime),
00196 mEventID(event.id()),
00197 mAlarmType(KAAlarm::MAIN_ALARM),
00198 mAction(event.action()),
00199 mKMailSerialNumber(0),
00200 mErrorMsgs(errmsgs),
00201 mRestoreHeight(0),
00202 mConfirmAck(false),
00203 mShowEdit(false),
00204 mNoDefer(true),
00205 mInvalid(false),
00206 mArtsDispatcher(0),
00207 mPlayObject(0),
00208 mEvent(event),
00209 mEditButton(0),
00210 mDeferButton(0),
00211 mSilenceButton(0),
00212 mDeferDlg(0),
00213 mWinModule(0),
00214 mErrorWindow(true),
00215 mNoPostAction(true),
00216 mRecreating(false),
00217 mRescheduleEvent(false),
00218 mShown(false),
00219 mPositioning(false),
00220 mNoCloseConfirm(false)
00221 {
00222 kdDebug(5950) << "MessageWin::MessageWin(errmsg)" << endl;
00223 initView();
00224 mWindowList.append(this);
00225 }
00226
00227
00228
00229
00230
00231 MessageWin::MessageWin()
00232 : MainWindowBase(0, "MessageWin", WFLAGS),
00233 mArtsDispatcher(0),
00234 mPlayObject(0),
00235 mEditButton(0),
00236 mDeferButton(0),
00237 mSilenceButton(0),
00238 mDeferDlg(0),
00239 mWinModule(0),
00240 mErrorWindow(false),
00241 mNoPostAction(true),
00242 mRecreating(false),
00243 mRescheduleEvent(false),
00244 mShown(false),
00245 mPositioning(false),
00246 mNoCloseConfirm(false)
00247 {
00248 kdDebug(5950) << "MessageWin::MessageWin()\n";
00249 mWindowList.append(this);
00250 }
00251
00252
00253
00254
00255 MessageWin::~MessageWin()
00256 {
00257 kdDebug(5950) << "MessageWin::~MessageWin()\n";
00258 stopPlay();
00259 delete mWinModule;
00260 mWinModule = 0;
00261 mWindowList.remove(this);
00262 if (!mRecreating)
00263 {
00264 if (!mNoPostAction && !mEvent.postAction().isEmpty())
00265 theApp()->alarmCompleted(mEvent);
00266 if (!mWindowList.count())
00267 theApp()->quitIf();
00268 }
00269 }
00270
00271
00272
00273
00274 void MessageWin::initView()
00275 {
00276 bool reminder = (!mErrorWindow && (mAlarmType & KAAlarm::REMINDER_ALARM));
00277 int leading = fontMetrics().leading();
00278 setCaption((mAlarmType & KAAlarm::REMINDER_ALARM) ? i18n("Reminder") : i18n("Message"));
00279 QWidget* topWidget = new QWidget(this, "messageWinTop");
00280 setCentralWidget(topWidget);
00281 QVBoxLayout* topLayout = new QVBoxLayout(topWidget, KDialog::marginHint(), KDialog::spacingHint());
00282
00283 if (mDateTime.isValid())
00284 {
00285
00286 QFrame* frame = 0;
00287 QVBoxLayout* layout = topLayout;
00288 if (reminder)
00289 {
00290 frame = new QFrame(topWidget);
00291 frame->setFrameStyle(QFrame::Box | QFrame::Raised);
00292 topLayout->addWidget(frame, 0, Qt::AlignHCenter);
00293 layout = new QVBoxLayout(frame, leading + frame->frameWidth(), leading);
00294 }
00295
00296
00297 QLabel* label = new QLabel(frame ? frame : topWidget);
00298 label->setText(mDateTime.isDateOnly()
00299 ? KGlobal::locale()->formatDate(mDateTime.date(), true)
00300 : KGlobal::locale()->formatDateTime(mDateTime.dateTime()));
00301 if (!frame)
00302 label->setFrameStyle(QFrame::Box | QFrame::Raised);
00303 label->setFixedSize(label->sizeHint());
00304 layout->addWidget(label, 0, Qt::AlignHCenter);
00305 QWhatsThis::add(label,
00306 i18n("The scheduled date/time for the message (as opposed to the actual time of display)."));
00307
00308 if (frame)
00309 {
00310 label = new QLabel(frame);
00311 label->setText(i18n("Reminder"));
00312 label->setFixedSize(label->sizeHint());
00313 layout->addWidget(label, 0, Qt::AlignHCenter);
00314 frame->setFixedSize(frame->sizeHint());
00315 }
00316 }
00317
00318 if (!mErrorWindow)
00319 {
00320
00321 switch (mAction)
00322 {
00323 case KAEvent::FILE:
00324 {
00325
00326 QLabel* label = new QLabel(mMessage, topWidget);
00327 label->setFrameStyle(QFrame::Box | QFrame::Raised);
00328 label->setFixedSize(label->sizeHint());
00329 QWhatsThis::add(label, i18n("The file whose contents are displayed below"));
00330 topLayout->addWidget(label, 0, Qt::AlignHCenter);
00331
00332
00333 bool opened = false;
00334 bool dir = false;
00335 QString tmpFile;
00336 KURL url(mMessage);
00337 if (KIO::NetAccess::download(url, tmpFile, MainWindow::mainMainWindow()))
00338 {
00339 QFile qfile(tmpFile);
00340 QFileInfo info(qfile);
00341 if (!(dir = info.isDir()))
00342 {
00343 opened = true;
00344 KTextBrowser* view = new KTextBrowser(topWidget, "fileContents");
00345 MWMimeSourceFactory msf(tmpFile, view);
00346 view->setMinimumSize(view->sizeHint());
00347 topLayout->addWidget(view);
00348
00349
00350
00351
00352
00353 int h = 20*view->fontMetrics().lineSpacing() + 2*view->frameWidth();
00354 view->resize(QSize(h, h).expandedTo(view->sizeHint()));
00355 QWhatsThis::add(view, i18n("The contents of the file to be displayed"));
00356 }
00357 KIO::NetAccess::removeTempFile(tmpFile);
00358 }
00359 if (!opened)
00360 {
00361
00362 bool exists = KIO::NetAccess::exists(url, true, MainWindow::mainMainWindow());
00363 mErrorMsgs += dir ? i18n("File is a folder") : exists ? i18n("Failed to open file") : i18n("File not found");
00364 }
00365 break;
00366 }
00367 case KAEvent::MESSAGE:
00368 {
00369
00370
00371 MessageText* text = new MessageText(mMessage, QString::null, topWidget);
00372 text->setFrameStyle(QFrame::NoFrame);
00373 text->setPaper(mBgColour);
00374 text->setPaletteForegroundColor(mFgColour);
00375 text->setFont(mFont);
00376 int lineSpacing = text->fontMetrics().lineSpacing();
00377 QSize s = text->sizeHint();
00378 int h = s.height();
00379 text->setMaximumHeight(h + text->scrollBarHeight());
00380 text->setMinimumHeight(QMIN(h, lineSpacing*4));
00381 text->setMaximumWidth(s.width() + text->scrollBarWidth());
00382 QWhatsThis::add(text, i18n("The alarm message"));
00383 int vspace = lineSpacing/2;
00384 int hspace = lineSpacing - KDialog::marginHint();
00385 topLayout->addSpacing(vspace);
00386 topLayout->addStretch();
00387
00388 if (!mWinModule)
00389 mWinModule = new KWinModule(0, KWinModule::INFO_DESKTOP);
00390 if (text->sizeHint().width() >= mWinModule->workArea().width()*2/3)
00391 topLayout->addWidget(text, 1, Qt::AlignHCenter);
00392 else
00393 {
00394 QBoxLayout* layout = new QHBoxLayout(topLayout);
00395 layout->addSpacing(hspace);
00396 layout->addWidget(text, 1, Qt::AlignHCenter);
00397 layout->addSpacing(hspace);
00398 }
00399 if (!reminder)
00400 topLayout->addStretch();
00401 break;
00402 }
00403 case KAEvent::COMMAND:
00404 case KAEvent::EMAIL:
00405 default:
00406 break;
00407 }
00408
00409 if (reminder)
00410 {
00411
00412 mRemainingText = new QLabel(topWidget);
00413 mRemainingText->setFrameStyle(QFrame::Box | QFrame::Raised);
00414 mRemainingText->setMargin(leading);
00415 if (mDateTime.isDateOnly() || QDate::currentDate().daysTo(mDateTime.date()) > 0)
00416 {
00417 setRemainingTextDay();
00418 MidnightTimer::connect(this, SLOT(setRemainingTextDay()));
00419 }
00420 else
00421 {
00422 setRemainingTextMinute();
00423 MinuteTimer::connect(this, SLOT(setRemainingTextMinute()));
00424 }
00425 topLayout->addWidget(mRemainingText, 0, Qt::AlignHCenter);
00426 topLayout->addSpacing(KDialog::spacingHint());
00427 topLayout->addStretch();
00428 }
00429 }
00430 else
00431 {
00432
00433 switch (mAction)
00434 {
00435 case KAEvent::EMAIL:
00436 {
00437
00438 QFrame* frame = new QFrame(topWidget);
00439 frame->setFrameStyle(QFrame::Box | QFrame::Raised);
00440 QWhatsThis::add(frame, i18n("The email to send"));
00441 topLayout->addWidget(frame, 0, Qt::AlignHCenter);
00442 QGridLayout* grid = new QGridLayout(frame, 2, 2, KDialog::marginHint(), KDialog::spacingHint());
00443
00444 QLabel* label = new QLabel(i18n("Email addressee", "To:"), frame);
00445 label->setFixedSize(label->sizeHint());
00446 grid->addWidget(label, 0, 0, Qt::AlignLeft);
00447 label = new QLabel(mEvent.emailAddresses("\n"), frame);
00448 label->setFixedSize(label->sizeHint());
00449 grid->addWidget(label, 0, 1, Qt::AlignLeft);
00450
00451 label = new QLabel(i18n("Email subject", "Subject:"), frame);
00452 label->setFixedSize(label->sizeHint());
00453 grid->addWidget(label, 1, 0, Qt::AlignLeft);
00454 label = new QLabel(mEvent.emailSubject(), frame);
00455 label->setFixedSize(label->sizeHint());
00456 grid->addWidget(label, 1, 1, Qt::AlignLeft);
00457 break;
00458 }
00459 case KAEvent::COMMAND:
00460 case KAEvent::FILE:
00461 case KAEvent::MESSAGE:
00462 default:
00463
00464 break;
00465 }
00466 }
00467
00468 if (!mErrorMsgs.count())
00469 topWidget->setBackgroundColor(mBgColour);
00470 else
00471 {
00472 setCaption(i18n("Error"));
00473 QBoxLayout* layout = new QHBoxLayout(topLayout);
00474 layout->setMargin(2*KDialog::marginHint());
00475 layout->addStretch();
00476 QLabel* label = new QLabel(topWidget);
00477 label->setPixmap(DesktopIcon("error"));
00478 label->setFixedSize(label->sizeHint());
00479 layout->addWidget(label, 0, Qt::AlignRight);
00480 QBoxLayout* vlayout = new QVBoxLayout(layout);
00481 for (QStringList::Iterator it = mErrorMsgs.begin(); it != mErrorMsgs.end(); ++it)
00482 {
00483 label = new QLabel(*it, topWidget);
00484 label->setFixedSize(label->sizeHint());
00485 vlayout->addWidget(label, 0, Qt::AlignLeft);
00486 }
00487 layout->addStretch();
00488 }
00489
00490 QGridLayout* grid = new QGridLayout(1, 4);
00491 topLayout->addLayout(grid);
00492 grid->setColStretch(0, 1);
00493 int gridIndex = 1;
00494
00495
00496 mOkButton = new KPushButton(KStdGuiItem::close(), topWidget);
00497
00498 mOkButton->clearFocus();
00499 mOkButton->setFocusPolicy(QWidget::ClickFocus);
00500 mOkButton->setFixedSize(mOkButton->sizeHint());
00501 connect(mOkButton, SIGNAL(clicked()), SLOT(close()));
00502 grid->addWidget(mOkButton, 0, gridIndex++, AlignHCenter);
00503 QWhatsThis::add(mOkButton, i18n("Acknowledge the alarm"));
00504
00505 if (mShowEdit)
00506 {
00507
00508 mEditButton = new QPushButton(i18n("&Edit..."), topWidget);
00509 mEditButton->setFocusPolicy(QWidget::ClickFocus);
00510 mEditButton->setFixedSize(mEditButton->sizeHint());
00511 connect(mEditButton, SIGNAL(clicked()), SLOT(slotEdit()));
00512 grid->addWidget(mEditButton, 0, gridIndex++, AlignHCenter);
00513 QWhatsThis::add(mEditButton, i18n("Edit the alarm."));
00514 }
00515
00516 if (!mNoDefer)
00517 {
00518
00519 mDeferButton = new QPushButton(i18n("&Defer..."), topWidget);
00520 mDeferButton->setFocusPolicy(QWidget::ClickFocus);
00521 mDeferButton->setFixedSize(mDeferButton->sizeHint());
00522 connect(mDeferButton, SIGNAL(clicked()), SLOT(slotDefer()));
00523 grid->addWidget(mDeferButton, 0, gridIndex++, AlignHCenter);
00524 QWhatsThis::add(mDeferButton,
00525 i18n("Defer the alarm until later.\n"
00526 "You will be prompted to specify when the alarm should be redisplayed."));
00527
00528 setDeferralLimit(mEvent);
00529 }
00530
00531 #ifndef WITHOUT_ARTS
00532 if (!mAudioFile.isEmpty() && (mVolume || mFadeVolume > 0))
00533 {
00534
00535 QPixmap pixmap = MainBarIcon("player_stop");
00536 mSilenceButton = new QPushButton(topWidget);
00537 mSilenceButton->setPixmap(pixmap);
00538 mSilenceButton->setFixedSize(mSilenceButton->sizeHint());
00539 connect(mSilenceButton, SIGNAL(clicked()), SLOT(stopPlay()));
00540 grid->addWidget(mSilenceButton, 0, gridIndex++, AlignHCenter);
00541 QToolTip::add(mSilenceButton, i18n("Stop sound"));
00542 QWhatsThis::add(mSilenceButton, i18n("Stop playing the sound"));
00543
00544 mSilenceButton->setEnabled(false);
00545 }
00546 #endif
00547
00548 KIconLoader iconLoader;
00549 if (mKMailSerialNumber)
00550 {
00551
00552 QPixmap pixmap = iconLoader.loadIcon(QString::fromLatin1("kmail"), KIcon::MainToolbar);
00553 mKMailButton = new QPushButton(topWidget);
00554 mKMailButton->setPixmap(pixmap);
00555 mKMailButton->setFixedSize(mKMailButton->sizeHint());
00556 connect(mKMailButton, SIGNAL(clicked()), SLOT(slotShowKMailMessage()));
00557 grid->addWidget(mKMailButton, 0, gridIndex++, AlignHCenter);
00558 QToolTip::add(mKMailButton, i18n("Locate this email in KMail", "Locate in KMail"));
00559 QWhatsThis::add(mKMailButton, i18n("Locate and highlight this email in KMail"));
00560 }
00561 else
00562 mKMailButton = 0;
00563
00564
00565 QPixmap pixmap = iconLoader.loadIcon(QString::fromLatin1(kapp->aboutData()->appName()), KIcon::MainToolbar);
00566 mKAlarmButton = new QPushButton(topWidget);
00567 mKAlarmButton->setPixmap(pixmap);
00568 mKAlarmButton->setFixedSize(mKAlarmButton->sizeHint());
00569 connect(mKAlarmButton, SIGNAL(clicked()), SLOT(displayMainWindow()));
00570 grid->addWidget(mKAlarmButton, 0, gridIndex++, AlignHCenter);
00571 QString actKAlarm = i18n("Activate KAlarm");
00572 QToolTip::add(mKAlarmButton, actKAlarm);
00573 QWhatsThis::add(mKAlarmButton, actKAlarm);
00574
00575
00576
00577 mOkButton->setEnabled(false);
00578 if (mDeferButton)
00579 mDeferButton->setEnabled(false);
00580 if (mEditButton)
00581 mEditButton->setEnabled(false);
00582 if (mKMailButton)
00583 mKMailButton->setEnabled(false);
00584 mKAlarmButton->setEnabled(false);
00585
00586 topLayout->activate();
00587 setMinimumSize(QSize(grid->sizeHint().width() + 2*KDialog::marginHint(), sizeHint().height()));
00588
00589 WId winid = winId();
00590 unsigned long wstate = (Preferences::modalMessages() ? NET::Modal : 0) | NET::Sticky | NET::StaysOnTop;
00591 KWin::setState(winid, wstate);
00592 KWin::setOnAllDesktops(winid, true);
00593 }
00594
00595
00596
00597
00598
00599 void MessageWin::setRemainingTextDay()
00600 {
00601 QString text;
00602 int days = QDate::currentDate().daysTo(mDateTime.date());
00603 if (days == 0 && !mDateTime.isDateOnly())
00604 {
00605
00606 MidnightTimer::disconnect(this, SLOT(setRemainingTextDay()));
00607 setRemainingTextMinute();
00608 MinuteTimer::connect(this, SLOT(setRemainingTextMinute()));
00609 }
00610 else
00611 {
00612 if (days == 0)
00613 text = i18n("Today");
00614 else if (days % 7)
00615 text = i18n("Tomorrow", "in %n days' time", days);
00616 else
00617 text = i18n("in 1 week's time", "in %n weeks' time", days/7);
00618 }
00619 mRemainingText->setText(text);
00620 }
00621
00622
00623
00624
00625
00626 void MessageWin::setRemainingTextMinute()
00627 {
00628 QString text;
00629 int mins = (QDateTime::currentDateTime().secsTo(mDateTime.dateTime()) + 59) / 60;
00630 if (mins < 60)
00631 text = i18n("in 1 minute's time", "in %n minutes' time", mins);
00632 else if (mins % 60 == 0)
00633 text = i18n("in 1 hour's time", "in %n hours' time", mins/60);
00634 else if (mins % 60 == 1)
00635 text = i18n("in 1 hour 1 minute's time", "in %n hours 1 minute's time", mins/60);
00636 else
00637 text = i18n("in 1 hour %1 minutes' time", "in %n hours %1 minutes' time", mins/60).arg(mins%60);
00638 mRemainingText->setText(text);
00639 }
00640
00641
00642
00643
00644
00645 void MessageWin::saveProperties(KConfig* config)
00646 {
00647 if (mShown && !mErrorWindow)
00648 {
00649 config->writeEntry(QString::fromLatin1("EventID"), mEventID);
00650 config->writeEntry(QString::fromLatin1("AlarmType"), mAlarmType);
00651 config->writeEntry(QString::fromLatin1("Message"), mMessage);
00652 config->writeEntry(QString::fromLatin1("Type"), mAction);
00653 config->writeEntry(QString::fromLatin1("Font"), mFont);
00654 config->writeEntry(QString::fromLatin1("BgColour"), mBgColour);
00655 config->writeEntry(QString::fromLatin1("FgColour"), mFgColour);
00656 config->writeEntry(QString::fromLatin1("ConfirmAck"), mConfirmAck);
00657 if (mDateTime.isValid())
00658 {
00659 config->writeEntry(QString::fromLatin1("Time"), mDateTime.dateTime());
00660 config->writeEntry(QString::fromLatin1("DateOnly"), mDateTime.isDateOnly());
00661 }
00662 if (mCloseTime.isValid())
00663 config->writeEntry(QString::fromLatin1("Expiry"), mCloseTime);
00664 #ifndef WITHOUT_ARTS
00665 if (mAudioRepeat && mSilenceButton && mSilenceButton->isEnabled())
00666 {
00667
00668 config->writePathEntry(QString::fromLatin1("AudioFile"), mAudioFile);
00669 config->writeEntry(QString::fromLatin1("Volume"), static_cast<int>(mVolume * 100));
00670 }
00671 #endif
00672 config->writeEntry(QString::fromLatin1("Speak"), mSpeak);
00673 config->writeEntry(QString::fromLatin1("Height"), height());
00674 config->writeEntry(QString::fromLatin1("NoDefer"), mNoDefer);
00675 config->writeEntry(QString::fromLatin1("KMailSerial"), mKMailSerialNumber);
00676 }
00677 else
00678 config->writeEntry(QString::fromLatin1("Invalid"), true);
00679 }
00680
00681
00682
00683
00684
00685
00686 void MessageWin::readProperties(KConfig* config)
00687 {
00688 mInvalid = config->readBoolEntry(QString::fromLatin1("Invalid"), false);
00689 mEventID = config->readEntry(QString::fromLatin1("EventID"));
00690 mAlarmType = KAAlarm::Type(config->readNumEntry(QString::fromLatin1("AlarmType")));
00691 mMessage = config->readEntry(QString::fromLatin1("Message"));
00692 mAction = KAEvent::Action(config->readNumEntry(QString::fromLatin1("Type")));
00693 mFont = config->readFontEntry(QString::fromLatin1("Font"));
00694 mBgColour = config->readColorEntry(QString::fromLatin1("BgColour"));
00695 mFgColour = config->readColorEntry(QString::fromLatin1("FgColour"));
00696 mConfirmAck = config->readBoolEntry(QString::fromLatin1("ConfirmAck"));
00697 QDateTime invalidDateTime;
00698 QDateTime dt = config->readDateTimeEntry(QString::fromLatin1("Time"), &invalidDateTime);
00699 bool dateOnly = config->readBoolEntry(QString::fromLatin1("DateOnly"));
00700 mDateTime.set(dt, dateOnly);
00701 mCloseTime = config->readDateTimeEntry(QString::fromLatin1("Expiry"), &invalidDateTime);
00702 #ifndef WITHOUT_ARTS
00703 mAudioFile = config->readPathEntry(QString::fromLatin1("AudioFile"));
00704 mVolume = static_cast<float>(config->readNumEntry(QString::fromLatin1("Volume"))) / 100;
00705 mFadeVolume = -1;
00706 mFadeSeconds = 0;
00707 if (!mAudioFile.isEmpty())
00708 mAudioRepeat = true;
00709 #endif
00710 mSpeak = config->readBoolEntry(QString::fromLatin1("Speak"));
00711 mRestoreHeight = config->readNumEntry(QString::fromLatin1("Height"));
00712 mNoDefer = config->readBoolEntry(QString::fromLatin1("NoDefer"));
00713 mKMailSerialNumber = config->readUnsignedLongNumEntry(QString::fromLatin1("KMailSerial"));
00714 mShowEdit = false;
00715 if (mAlarmType != KAAlarm::INVALID_ALARM)
00716 {
00717
00718 if (!mEventID.isEmpty())
00719 {
00720 const Event* kcalEvent = AlarmCalendar::activeCalendar()->event(mEventID);
00721 if (!kcalEvent)
00722 {
00723
00724 AlarmCalendar* cal = AlarmCalendar::displayCalendar();
00725 if (cal->isOpen())
00726 kcalEvent = cal->event(KAEvent::uid(mEventID, KAEvent::DISPLAYING));
00727 }
00728 if (kcalEvent)
00729 {
00730 mEvent.set(*kcalEvent);
00731 mEvent.setUid(KAEvent::ACTIVE);
00732 mShowEdit = true;
00733 }
00734 }
00735 initView();
00736 }
00737 }
00738
00739
00740
00741
00742
00743 MessageWin* MessageWin::findEvent(const QString& eventID)
00744 {
00745 for (QValueList<MessageWin*>::Iterator it = mWindowList.begin(); it != mWindowList.end(); ++it)
00746 {
00747 MessageWin* w = *it;
00748 if (w->mEventID == eventID && !w->mErrorWindow)
00749 return w;
00750 }
00751 return 0;
00752 }
00753
00754
00755
00756
00757 void MessageWin::playAudio()
00758 {
00759 if (mBeep)
00760 {
00761
00762 KNotifyClient::beep();
00763 QApplication::beep();
00764 }
00765 if (!mAudioFile.isEmpty())
00766 {
00767 if (!mVolume && mFadeVolume <= 0)
00768 return;
00769 #ifdef WITHOUT_ARTS
00770 QString play = mAudioFile;
00771 QString file = QString::fromLatin1("file:");
00772 if (mAudioFile.startsWith(file))
00773 play = mAudioFile.mid(file.length());
00774 KAudioPlayer::play(QFile::encodeName(play));
00775 #else
00776
00777
00778 QTimer::singleShot(0, this, SLOT(slotPlayAudio()));
00779 #endif
00780 }
00781 else if (mSpeak)
00782 {
00783
00784
00785 QTimer::singleShot(0, this, SLOT(slotSpeak()));
00786 }
00787 }
00788
00789
00790
00791
00792
00793 void MessageWin::slotSpeak()
00794 {
00795 DCOPClient* client = kapp->dcopClient();
00796 if (!client->isApplicationRegistered("kttsd"))
00797 {
00798
00799 QString error;
00800 if (kapp->startServiceByDesktopName("kttsd", QStringList(), &error))
00801 {
00802 kdDebug(5950) << "MessageWin::slotSpeak(): failed to start kttsd: " << error << endl;
00803 KMessageBox::detailedError(0, i18n("Unable to speak message"), error);
00804 return;
00805 }
00806 }
00807 QByteArray data;
00808 QDataStream arg(data, IO_WriteOnly);
00809 arg << mMessage << "";
00810 if (!client->send("kttsd", "KSpeech", "sayMessage(QString,QString)", data))
00811 {
00812 kdDebug(5950) << "MessageWin::slotSpeak(): sayMessage() DCOP error" << endl;
00813 KMessageBox::detailedError(0, i18n("Unable to speak message"), i18n("DCOP Call sayMessage failed"));
00814 }
00815 }
00816
00817
00818
00819
00820
00821 void MessageWin::slotPlayAudio()
00822 {
00823 #ifndef WITHOUT_ARTS
00824
00825 MainWindow* mmw = MainWindow::mainMainWindow();
00826 KURL url(mAudioFile);
00827 if (!url.isValid() || !KIO::NetAccess::exists(url, true, mmw)
00828 || !KIO::NetAccess::download(url, mLocalAudioFile, mmw))
00829 {
00830 kdError(5950) << "MessageWin::playAudio(): Open failure: " << mAudioFile << endl;
00831 KMessageBox::error(this, i18n("Cannot open audio file:\n%1").arg(mAudioFile));
00832 return;
00833 }
00834 if (!mArtsDispatcher)
00835 {
00836 mFadeTimer = 0;
00837 mPlayTimer = new QTimer(this);
00838 connect(mPlayTimer, SIGNAL(timeout()), SLOT(checkAudioPlay()));
00839 mArtsDispatcher = new KArtsDispatcher;
00840 mPlayedOnce = false;
00841 mAudioFileStart = QTime::currentTime();
00842 initAudio(true);
00843 if (!mPlayObject->object().isNull())
00844 checkAudioPlay();
00845 #if KDE_VERSION >= 308
00846 if (!mUsingKMix && mVolume >= 0)
00847 {
00848
00849
00850 KMessageBox::information(this, i18n("Unable to set master volume\n(Error accessing KMix:\n%1)").arg(mKMixError),
00851 QString::null, QString::fromLatin1("KMixError"));
00852 kdWarning(5950) << "Unable to set master volume (KMix: " << mKMixError << ")\n";
00853 }
00854 #endif
00855 }
00856 #endif
00857 }
00858
00859 #ifndef WITHOUT_ARTS
00860
00861
00862
00863 void MessageWin::initAudio(bool firstTime)
00864 {
00865 KArtsServer aserver;
00866 Arts::SoundServerV2 sserver = aserver.server();
00867 KDE::PlayObjectFactory factory(sserver);
00868 mPlayObject = factory.createPlayObject(mLocalAudioFile, true);
00869 if (firstTime)
00870 {
00871
00872
00873 mUsingKMix = false;
00874 float volume = mVolume;
00875 if (volume >= 0)
00876 {
00877
00878 if (mFadeVolume >= 0)
00879 volume = mFadeVolume;
00880
00881
00882 int vol = getKMixVolume();
00883 if (vol >= 0)
00884 {
00885 mOldVolume = vol;
00886 mUsingKMix = true;
00887 setKMixVolume(static_cast<int>(volume * 100));
00888 }
00889 }
00890 if (!mUsingKMix)
00891 {
00892
00893
00894
00895
00896
00897 mOldVolume = sserver.outVolume().scaleFactor();
00898 sserver.outVolume().scaleFactor(volume >= 0 ? volume : 1);
00899 }
00900 }
00901 mSilenceButton->setEnabled(true);
00902 mPlayed = false;
00903 connect(mPlayObject, SIGNAL(playObjectCreated()), SLOT(checkAudioPlay()));
00904 if (!mPlayObject->object().isNull())
00905 checkAudioPlay();
00906 }
00907 #endif
00908
00909
00910
00911
00912
00913
00914
00915 void MessageWin::checkAudioPlay()
00916 {
00917 #ifndef WITHOUT_ARTS
00918 if (!mPlayObject)
00919 return;
00920 if (mPlayObject->state() == Arts::posIdle)
00921 {
00922
00923 if (mPlayedOnce && !mAudioRepeat)
00924 {
00925
00926 stopPlay();
00927 return;
00928 }
00929
00930
00931 kdDebug(5950) << "MessageWin::checkAudioPlay(): start\n";
00932 if (!mPlayedOnce)
00933 {
00934
00935 QTime now = QTime::currentTime();
00936 mAudioFileLoadSecs = mAudioFileStart.secsTo(now);
00937 if (mAudioFileLoadSecs < 0)
00938 mAudioFileLoadSecs += 86400;
00939 if (mVolume >= 0 && mFadeVolume >= 0 && mFadeSeconds > 0)
00940 {
00941
00942 mAudioFileStart = now;
00943 mFadeTimer = new QTimer(this);
00944 connect(mFadeTimer, SIGNAL(timeout()), SLOT(slotFade()));
00945 mFadeTimer->start(1000);
00946 }
00947 mPlayedOnce = true;
00948 }
00949 if (mAudioFileLoadSecs < 3)
00950 {
00951
00952
00953
00954
00955
00956 if (mPlayed)
00957 {
00958
00959 delete mPlayObject;
00960 initAudio(false);
00961 if (mPlayObject->object().isNull())
00962 return;
00963 }
00964 mPlayed = true;
00965 mPlayObject->play();
00966 }
00967 else
00968 {
00969
00970 static Arts::poTime t0((long)0, (long)0, 0, std::string());
00971 Arts::poTime current = mPlayObject->currentTime();
00972 if (current.seconds || current.ms)
00973 mPlayObject->seek(t0);
00974 else
00975 mPlayObject->play();
00976 }
00977 }
00978
00979
00980 Arts::poTime overall = mPlayObject->overallTime();
00981 Arts::poTime current = mPlayObject->currentTime();
00982 int time = 1000*(overall.seconds - current.seconds) + overall.ms - current.ms;
00983 if (time < 0)
00984 time = 0;
00985 kdDebug(5950) << "MessageWin::checkAudioPlay(): wait for " << (time+100) << "ms\n";
00986 mPlayTimer->start(time + 100, true);
00987 #endif
00988 }
00989
00990
00991
00992
00993
00994 void MessageWin::stopPlay()
00995 {
00996 #ifndef WITHOUT_ARTS
00997 if (mArtsDispatcher)
00998 {
00999
01000
01001 if (!mUsingKMix)
01002 {
01003 KArtsServer aserver;
01004 Arts::StereoVolumeControl svc = aserver.server().outVolume();
01005 float currentVolume = svc.scaleFactor();
01006 float eventVolume = mVolume;
01007 if (eventVolume < 0)
01008 eventVolume = 1;
01009 if (currentVolume == eventVolume)
01010 svc.scaleFactor(mOldVolume);
01011 }
01012 else if (mVolume >= 0)
01013 {
01014 int eventVolume = static_cast<int>(mVolume * 100);
01015 int currentVolume = getKMixVolume();
01016
01017 if (currentVolume < 0 || abs(currentVolume - eventVolume) < 5)
01018 setKMixVolume(static_cast<int>(mOldVolume));
01019 }
01020 }
01021 delete mPlayObject; mPlayObject = 0;
01022 delete mArtsDispatcher; mArtsDispatcher = 0;
01023 if (!mLocalAudioFile.isEmpty())
01024 {
01025 KIO::NetAccess::removeTempFile(mLocalAudioFile);
01026 mLocalAudioFile = QString::null;
01027 }
01028 if (mSilenceButton)
01029 mSilenceButton->setEnabled(false);
01030 #endif
01031 }
01032
01033
01034
01035
01036 void MessageWin::slotFade()
01037 {
01038 #ifndef WITHOUT_ARTS
01039 QTime now = QTime::currentTime();
01040 int elapsed = mAudioFileStart.secsTo(now);
01041 if (elapsed < 0)
01042 elapsed += 86400;
01043 float volume;
01044 if (elapsed >= mFadeSeconds)
01045 {
01046
01047 volume = mVolume;
01048 delete mFadeTimer;
01049 mFadeTimer = 0;
01050 if (!mVolume)
01051 {
01052 kdDebug(5950) << "MessageWin::slotFade(0)\n";
01053 stopPlay();
01054 return;
01055 }
01056 }
01057 else
01058 volume = mFadeVolume + ((mVolume - mFadeVolume) * elapsed) / mFadeSeconds;
01059 kdDebug(5950) << "MessageWin::slotFade(" << volume << ")\n";
01060 if (mArtsDispatcher)
01061 {
01062 if (mUsingKMix)
01063 setKMixVolume(static_cast<int>(volume * 100));
01064 else if (mArtsDispatcher)
01065 {
01066 KArtsServer aserver;
01067 aserver.server().outVolume().scaleFactor(volume);
01068 }
01069 }
01070 #endif
01071 }
01072
01073 #ifndef WITHOUT_ARTS
01074
01075
01076
01077
01078 int MessageWin::getKMixVolume()
01079 {
01080 if (!KAlarm::runProgram(KMIX_APP_NAME, KMIX_DCOP_WINDOW, mKMixName, mKMixError))
01081 return -1;
01082 QByteArray data, replyData;
01083 QCString replyType;
01084 QDataStream arg(data, IO_WriteOnly);
01085 if (!kapp->dcopClient()->call(mKMixName, KMIX_DCOP_OBJECT, "masterVolume()", data, replyType, replyData)
01086 || replyType != "int")
01087 return -1;
01088 int result;
01089 QDataStream reply(replyData, IO_ReadOnly);
01090 reply >> result;
01091 return (result >= 0) ? result : 0;
01092 }
01093
01094
01095
01096
01097 void MessageWin::setKMixVolume(int percent)
01098 {
01099 if (!mUsingKMix)
01100 return;
01101 if (!KAlarm::runProgram(KMIX_APP_NAME, KMIX_DCOP_WINDOW, mKMixName, mKMixError))
01102 return;
01103 QByteArray data;
01104 QDataStream arg(data, IO_WriteOnly);
01105 arg << percent;
01106 if (!kapp->dcopClient()->send(mKMixName, KMIX_DCOP_OBJECT, "setMasterVolume(int)", data))
01107 kdError(5950) << "MessageWin::setKMixVolume(): kmix dcop call failed\n";
01108 }
01109 #endif
01110
01111
01112
01113
01114
01115 void MessageWin::repeat(const KAAlarm& alarm)
01116 {
01117 if (mDeferDlg)
01118 {
01119
01120
01121 delete mDeferDlg;
01122 mDeferDlg = 0;
01123 }
01124 const Event* kcalEvent = mEventID.isNull() ? 0 : AlarmCalendar::activeCalendar()->event(mEventID);
01125 if (kcalEvent)
01126 {
01127 mAlarmType = alarm.type();
01128 if (!mDeferDlg || Preferences::modalMessages())
01129 {
01130 raise();
01131 playAudio();
01132 }
01133 KAEvent event(*kcalEvent);
01134 mDeferButton->setEnabled(true);
01135 setDeferralLimit(event);
01136 theApp()->alarmShowing(event, mAlarmType, mDateTime);
01137 }
01138 }
01139
01140
01141
01142
01143
01144
01145
01146 void MessageWin::show()
01147 {
01148 if (mCloseTime.isValid())
01149 {
01150
01151 int delay = QDateTime::currentDateTime().secsTo(mCloseTime);
01152 if (delay < 0)
01153 delay = 0;
01154 QTimer::singleShot(delay * 1000, this, SLOT(close()));
01155 if (!delay)
01156 return;
01157 }
01158 if (Preferences::messageButtonDelay() == 0)
01159 move(0, 0);
01160 MainWindowBase::show();
01161 }
01162
01163
01164
01165
01166
01167
01168 QSize MessageWin::sizeHint() const
01169 {
01170 if (mAction != KAEvent::MESSAGE)
01171 return MainWindowBase::sizeHint();
01172 if (!mWinModule)
01173 mWinModule = new KWinModule(0, KWinModule::INFO_DESKTOP);
01174 QSize frame = frameGeometry().size();
01175 QSize contents = geometry().size();
01176 QSize desktop = mWinModule->workArea().size();
01177 QSize maxSize(desktop.width() - (frame.width() - contents.width()),
01178 desktop.height() - (frame.height() - contents.height()));
01179 return MainWindowBase::sizeHint().boundedTo(maxSize);
01180 }
01181
01182
01183
01184
01185
01186
01187 void MessageWin::showEvent(QShowEvent* se)
01188 {
01189 MainWindowBase::showEvent(se);
01190 if (!mShown)
01191 {
01192 if (mErrorWindow)
01193 enableButtons();
01194 else
01195 {
01196
01197
01198
01199
01200
01201 QSize s = sizeHint();
01202 if (mAction == KAEvent::FILE && !mErrorMsgs.count())
01203 KAlarm::readConfigWindowSize("FileMessage", s);
01204 resize(s);
01205
01206 mButtonDelay = Preferences::messageButtonDelay() * 1000;
01207 if (!mButtonDelay)
01208 {
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 QPoint cursor = QCursor::pos();
01227 if (!mWinModule)
01228 mWinModule = new KWinModule(0, KWinModule::INFO_DESKTOP);
01229 QRect desk = mWinModule->workArea();
01230 QDesktopWidget* dw = QApplication::desktop();
01231 if (dw->numScreens() > 1)
01232 desk &= dw->screenGeometry(dw->screenNumber(cursor));
01233
01234 QRect frame = frameGeometry();
01235 QRect rect = geometry();
01236
01237 QRect button(mOkButton->mapToParent(QPoint(0, 0)), mOkButton->mapToParent(mOkButton->rect().bottomRight()));
01238 int buttonLeft = button.left() + rect.left() - frame.left();
01239 int buttonRight = width() - button.right() + frame.right() - rect.right();
01240 int buttonTop = button.top() + rect.top() - frame.top();
01241 int buttonBottom = height() - button.bottom() + frame.bottom() - rect.bottom();
01242
01243 int centrex = (desk.width() + buttonLeft - buttonRight) / 2;
01244 int centrey = (desk.height() + buttonTop - buttonBottom) / 2;
01245 int x = (cursor.x() < centrex) ? desk.right() - frame.width() : desk.left();
01246 int y = (cursor.y() < centrey) ? desk.bottom() - frame.height() : desk.top();
01247
01248
01249
01250 QRect buttons = mOkButton->geometry().unite(mKAlarmButton->geometry());
01251 buttons.moveBy(rect.left() + x - frame.left(), rect.top() + y - frame.top());
01252 int minDistance = proximityMultiple * mOkButton->height();
01253 if ((abs(cursor.x() - buttons.left()) < minDistance
01254 || abs(cursor.x() - buttons.right()) < minDistance)
01255 && (abs(cursor.y() - buttons.top()) < minDistance
01256 || abs(cursor.y() - buttons.bottom()) < minDistance))
01257 mButtonDelay = proximityButtonDelay;
01258
01259 if (x != frame.left() || y != frame.top())
01260 {
01261 mPositioning = true;
01262 move(x, y);
01263 }
01264 }
01265 if (!mPositioning)
01266 displayComplete();
01267 if (mAction == KAEvent::MESSAGE)
01268 {
01269
01270 QTimer::singleShot(0, this, SLOT(setMaxSize()));
01271 }
01272 }
01273 mShown = true;
01274 }
01275 }
01276
01277
01278
01279
01280 void MessageWin::moveEvent(QMoveEvent* e)
01281 {
01282 MainWindowBase::moveEvent(e);
01283 if (mPositioning)
01284 {
01285
01286 mPositioning = false;
01287 displayComplete();
01288 }
01289 }
01290
01291
01292
01293
01294 void MessageWin::setMaxSize()
01295 {
01296 QSize s = sizeHint();
01297 if (width() > s.width() || height() > s.height())
01298 resize(s);
01299 }
01300
01301
01302
01303
01304
01305 void MessageWin::displayComplete()
01306 {
01307 playAudio();
01308 if (mRescheduleEvent)
01309 theApp()->alarmShowing(mEvent, mAlarmType, mDateTime);
01310
01311
01312 if (mButtonDelay > 0)
01313 QTimer::singleShot(mButtonDelay, this, SLOT(enableButtons()));
01314 else
01315 enableButtons();
01316 }
01317
01318
01319
01320
01321 void MessageWin::enableButtons()
01322 {
01323 mOkButton->setEnabled(true);
01324 mKAlarmButton->setEnabled(true);
01325 if (mDeferButton)
01326 mDeferButton->setEnabled(true);
01327 if (mEditButton)
01328 mEditButton->setEnabled(true);
01329 if (mKMailButton)
01330 mKMailButton->setEnabled(true);
01331 }
01332
01333
01334
01335
01336 void MessageWin::resizeEvent(QResizeEvent* re)
01337 {
01338 if (mRestoreHeight)
01339 {
01340
01341 if (mRestoreHeight != re->size().height())
01342 {
01343 QSize size = re->size();
01344 size.setHeight(mRestoreHeight);
01345 resize(size);
01346 }
01347 else if (isVisible())
01348 mRestoreHeight = 0;
01349 }
01350 else
01351 {
01352 if (mShown && mAction == KAEvent::FILE && !mErrorMsgs.count())
01353 KAlarm::writeConfigWindowSize("FileMessage", re->size());
01354 MainWindowBase::resizeEvent(re);
01355 }
01356 }
01357
01358
01359
01360
01361
01362 void MessageWin::closeEvent(QCloseEvent* ce)
01363 {
01364
01365 if (!theApp()->sessionClosingDown())
01366 {
01367 if (mConfirmAck && !mNoCloseConfirm)
01368 {
01369
01370 if (KMessageBox::warningYesNo(this, i18n("Do you really want to acknowledge this alarm?"),
01371 i18n("Acknowledge Alarm"), i18n("&Acknowledge"), KStdGuiItem::cancel())
01372 != KMessageBox::Yes)
01373 {
01374 ce->ignore();
01375 return;
01376 }
01377 }
01378 if (!mEventID.isNull())
01379 {
01380
01381 KAlarm::deleteDisplayEvent(KAEvent::uid(mEventID, KAEvent::DISPLAYING));
01382 }
01383 }
01384 MainWindowBase::closeEvent(ce);
01385 }
01386
01387
01388
01389
01390
01391 void MessageWin::slotShowKMailMessage()
01392 {
01393 kdDebug(5950) << "MessageWin::slotShowKMailMessage()\n";
01394 if (!mKMailSerialNumber)
01395 return;
01396 QString err = KAlarm::runKMail(false);
01397 if (!err.isNull())
01398 {
01399 KMessageBox::sorry(this, err);
01400 return;
01401 }
01402 QCString replyType;
01403 QByteArray data, replyData;
01404 QDataStream arg(data, IO_WriteOnly);
01405 arg << (Q_UINT32)mKMailSerialNumber << QString::null;
01406 if (kapp->dcopClient()->call("kmail", KMAIL_DCOP_OBJECT, "showMail(Q_UINT32,QString)", data, replyType, replyData)
01407 && replyType == "bool")
01408 {
01409 bool result;
01410 QDataStream replyStream(replyData, IO_ReadOnly);
01411 replyStream >> result;
01412 if (result)
01413 return;
01414 }
01415 kdError(5950) << "MessageWin::slotShowKMailMessage(): kmail dcop call failed\n";
01416 KMessageBox::sorry(this, i18n("Unable to locate this email in KMail"));
01417 }
01418
01419
01420
01421
01422
01423 void MessageWin::slotEdit()
01424 {
01425 kdDebug(5950) << "MessageWin::slotEdit()" << endl;
01426 EditAlarmDlg editDlg(false, i18n("Edit Alarm"), this, "editDlg", &mEvent);
01427 if (editDlg.exec() == QDialog::Accepted)
01428 {
01429 KAEvent event;
01430 editDlg.getEvent(event);
01431
01432
01433 KAlarm::UpdateStatus status;
01434 if (AlarmCalendar::activeCalendar()->event(mEventID))
01435 {
01436
01437 status = KAlarm::modifyEvent(mEvent, event, 0);
01438 Undo::saveEdit(mEvent, event);
01439 }
01440 else
01441 {
01442
01443 status = KAlarm::addEvent(event, 0);
01444 Undo::saveAdd(event);
01445 }
01446
01447 if (status == KAlarm::UPDATE_KORG_ERR)
01448 KAlarm::displayKOrgUpdateError(this, KAlarm::KORG_ERR_MODIFY, 1);
01449 KAlarm::outputAlarmWarnings(&editDlg, &event);
01450
01451
01452 mNoCloseConfirm = true;
01453 close();
01454 }
01455 }
01456
01457
01458
01459
01460 void MessageWin::setDeferralLimit(const KAEvent& event)
01461 {
01462 if (mDeferButton)
01463 {
01464 mDeferLimit = event.deferralLimit().dateTime();
01465 MidnightTimer::connect(this, SLOT(checkDeferralLimit()));
01466 checkDeferralLimit();
01467 }
01468 }
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479 void MessageWin::checkDeferralLimit()
01480 {
01481 if (!mDeferButton || !mDeferLimit.isValid())
01482 return;
01483 int n = QDate::currentDate().daysTo(mDeferLimit.date());
01484 if (n > 0)
01485 return;
01486 MidnightTimer::disconnect(this, SLOT(checkDeferralLimit()));
01487 if (n == 0)
01488 {
01489
01490 n = QTime::currentTime().secsTo(mDeferLimit.time());
01491 if (n > 0)
01492 {
01493 QTimer::singleShot(n * 1000, this, SLOT(checkDeferralLimit()));
01494 return;
01495 }
01496 }
01497 mDeferButton->setEnabled(false);
01498 }
01499
01500
01501
01502
01503
01504 void MessageWin::slotDefer()
01505 {
01506 mDeferDlg = new DeferAlarmDlg(i18n("Defer Alarm"), QDateTime::currentDateTime().addSecs(60),
01507 false, this, "deferDlg");
01508 mDeferDlg->setLimit(mEventID);
01509 if (!Preferences::modalMessages())
01510 lower();
01511 if (mDeferDlg->exec() == QDialog::Accepted)
01512 {
01513 DateTime dateTime = mDeferDlg->getDateTime();
01514 const Event* kcalEvent = mEventID.isNull() ? 0 : AlarmCalendar::activeCalendar()->event(mEventID);
01515 if (kcalEvent)
01516 {
01517
01518 KAEvent event(*kcalEvent);
01519 bool repeat = event.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM), true);
01520 KAlarm::updateEvent(event, 0, true, !repeat);
01521 }
01522 else
01523 {
01524 KAEvent event;
01525 kcalEvent = AlarmCalendar::displayCalendar()->event(KAEvent::uid(mEventID, KAEvent::DISPLAYING));
01526 if (kcalEvent)
01527 {
01528 event.reinstateFromDisplaying(KAEvent(*kcalEvent));
01529 event.defer(dateTime, (mAlarmType & KAAlarm::REMINDER_ALARM), true);
01530 }
01531 else
01532 {
01533
01534 event.set(dateTime.dateTime(), mMessage, mBgColour, mFgColour, mFont, mAction, mLateCancel, mFlags);
01535 event.setAudioFile(mAudioFile, mVolume, mFadeVolume, mFadeSeconds);
01536 event.setArchive();
01537 event.setEventID(mEventID);
01538 }
01539
01540
01541 KAlarm::addEvent(event, 0, true, false);
01542 if (kcalEvent)
01543 {
01544 event.setUid(KAEvent::EXPIRED);
01545 KAlarm::deleteEvent(event, false);
01546 }
01547 }
01548 if (theApp()->wantRunInSystemTray())
01549 {
01550
01551
01552 theApp()->displayTrayIcon(true);
01553 }
01554 mNoCloseConfirm = true;
01555 close();
01556 }
01557 else
01558 raise();
01559 delete mDeferDlg;
01560 mDeferDlg = 0;
01561 }
01562
01563
01564
01565
01566
01567 void MessageWin::displayMainWindow()
01568 {
01569 KAlarm::displayMainWindowSelected(mEventID);
01570 }
01571
01572
01573
01574
01575
01576
01577
01578
01579 MWMimeSourceFactory::MWMimeSourceFactory(const QString& absPath, KTextBrowser* view)
01580 : QMimeSourceFactory(),
01581 mMimeType("text/plain"),
01582 mLast(0)
01583 {
01584 view->setMimeSourceFactory(this);
01585 QString type = KMimeType::findByPath(absPath)->name();
01586 switch (KAlarm::fileType(type))
01587 {
01588 case KAlarm::TextPlain:
01589 case KAlarm::TextFormatted:
01590 mMimeType = type.latin1();
01591
01592 case KAlarm::TextApplication:
01593 default:
01594
01595 mTextFile = absPath;
01596 view->QTextBrowser::setSource(absPath);
01597 break;
01598
01599 case KAlarm::Image:
01600
01601 QString text = "<img source=\"";
01602 text += absPath;
01603 text += "\">";
01604 view->setText(text);
01605 break;
01606 }
01607 setFilePath(QFileInfo(absPath).dirPath(true));
01608 }
01609
01610 MWMimeSourceFactory::~MWMimeSourceFactory()
01611 {
01612 delete mLast;
01613 }
01614
01615 const QMimeSource* MWMimeSourceFactory::data(const QString& abs_name) const
01616 {
01617 if (abs_name == mTextFile)
01618 {
01619 QFileInfo fi(abs_name);
01620 if (fi.isReadable())
01621 {
01622 QFile f(abs_name);
01623 if (f.open(IO_ReadOnly) && f.size())
01624 {
01625 QByteArray ba(f.size());
01626 f.readBlock(ba.data(), ba.size());
01627 QStoredDrag* sr = new QStoredDrag(mMimeType);
01628 sr->setEncodedData(ba);
01629 delete mLast;
01630 mLast = sr;
01631 return sr;
01632 }
01633 }
01634 }
01635 return QMimeSourceFactory::data(abs_name);
01636 }