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