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