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