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