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