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 <QGroupBox>
00024 #include <QCheckBox>
00025 #include <QVBoxLayout>
00026 #include <QGridLayout>
00027
00028 #include <kfinddialog.h>
00029 #include <kfind.h>
00030 #include <kseparator.h>
00031 #include <kwindowsystem.h>
00032 #include <klocale.h>
00033 #include <kmessagebox.h>
00034 #include <kdebug.h>
00035
00036 #include "alarmevent.h"
00037 #include "alarmlistfiltermodel.h"
00038 #include "alarmlistview.h"
00039 #include "eventlistview.h"
00040 #include "preferences.h"
00041 #include "find.moc"
00042
00043 #ifdef __GNUC__
00044 #warning Search for text, then '29', then '2', reverts to text
00045 #endif
00046
00047 enum {
00048 FIND_LIVE = KFind::MinimumUserOption,
00049 FIND_ARCHIVED = KFind::MinimumUserOption << 1,
00050 FIND_MESSAGE = KFind::MinimumUserOption << 2,
00051 FIND_FILE = KFind::MinimumUserOption << 3,
00052 FIND_COMMAND = KFind::MinimumUserOption << 4,
00053 FIND_EMAIL = KFind::MinimumUserOption << 5
00054 };
00055 static long FIND_KALARM_OPTIONS = FIND_LIVE | FIND_ARCHIVED | FIND_MESSAGE | FIND_FILE | FIND_COMMAND | FIND_EMAIL;
00056
00057
00058 class FindDlg : public KFindDialog
00059 {
00060 public:
00061 FindDlg(QWidget* parent, long options = 0, const QStringList& findStrings = QStringList(), bool hasSelection = false)
00062 : KFindDialog(parent, options, findStrings, hasSelection) {}
00063 protected slots:
00064 void slotButtonClicked(int button)
00065 {
00066 if (button == Ok)
00067 emit okClicked();
00068 else
00069 KFindDialog::slotButtonClicked(button);
00070 }
00071 };
00072
00073
00074 Find::Find(EventListView* parent)
00075 : QObject(parent),
00076 mListView(parent),
00077 mDialog(0),
00078 mFind(0),
00079 mOptions(0)
00080 {
00081 connect(mListView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&,const QModelIndex&)), SLOT(slotSelectionChanged()));
00082 }
00083
00084 Find::~Find()
00085 {
00086 delete mDialog;
00087 delete mFind;
00088 mFind = 0;
00089 }
00090
00091 void Find::slotSelectionChanged()
00092 {
00093 if (mDialog)
00094 mDialog->setHasCursor(mListView->selectionModel()->currentIndex().isValid());
00095 }
00096
00097
00098
00099
00100 void Find::display()
00101 {
00102 if (!mOptions)
00103
00104 mOptions = FIND_LIVE | FIND_ARCHIVED | FIND_MESSAGE | FIND_FILE | FIND_COMMAND | FIND_EMAIL;
00105 bool noArchived = !Preferences::archivedKeepDays();
00106 bool showArchived = qobject_cast<AlarmListView*>(mListView)
00107 && (static_cast<AlarmListFilterModel*>(mListView->model())->statusFilter() & KCalEvent::ARCHIVED);
00108 if (noArchived || !showArchived)
00109 mOptions &= ~FIND_ARCHIVED;
00110
00111 if (mDialog)
00112 {
00113 #ifdef Q_WS_X11
00114 KWindowSystem::activateWindow(mDialog->winId());
00115 #endif
00116 }
00117 else
00118 {
00119 mDialog = new FindDlg(mListView, mOptions, mHistory, (mListView->selectionModel()->selectedRows().count() > 1));
00120 mDialog->setModal(false);
00121 mDialog->setObjectName("FindDlg");
00122 mDialog->setHasSelection(false);
00123 QWidget* kalarmWidgets = mDialog->findExtension();
00124
00125
00126 QVBoxLayout* layout = new QVBoxLayout(kalarmWidgets);
00127 layout->setMargin(0);
00128 layout->setSpacing(KDialog::spacingHint());
00129 QGroupBox* group = new QGroupBox(i18nc("@title:group", "Alarm Type"), kalarmWidgets);
00130 layout->addWidget(group);
00131 QGridLayout* grid = new QGridLayout(group);
00132 grid->setMargin(KDialog::marginHint());
00133 grid->setSpacing(KDialog::spacingHint());
00134 grid->setColumnStretch(1, 1);
00135
00136
00137 mLive = new QCheckBox(i18nc("@option:check Alarm type", "Active"), group);
00138 mLive->setFixedSize(mLive->sizeHint());
00139 mLive->setWhatsThis(i18nc("@info:whatsthis", "Check to include active alarms in the search."));
00140 grid->addWidget(mLive, 1, 0, Qt::AlignLeft);
00141
00142 mArchived = new QCheckBox(i18nc("@option:check Alarm type", "Archived"), group);
00143 mArchived->setFixedSize(mArchived->sizeHint());
00144 mArchived->setWhatsThis(i18nc("@info:whatsthis", "Check to include archived alarms in the search. "
00145 "This option is only available if archived alarms are currently being displayed."));
00146 grid->addWidget(mArchived, 1, 2, Qt::AlignLeft);
00147
00148 mActiveArchivedSep = new KSeparator(Qt::Horizontal, kalarmWidgets);
00149 grid->addWidget(mActiveArchivedSep, 2, 0, 1, 3);
00150
00151
00152 mMessageType = new QCheckBox(i18nc("@option:check Alarm action = text display", "Text"), group);
00153 mMessageType->setFixedSize(mMessageType->sizeHint());
00154 mMessageType->setWhatsThis(i18nc("@info:whatsthis", "Check to include text message alarms in the search."));
00155 grid->addWidget(mMessageType, 3, 0);
00156
00157 mFileType = new QCheckBox(i18nc("@option:check Alarm action = file display", "File"), group);
00158 mFileType->setFixedSize(mFileType->sizeHint());
00159 mFileType->setWhatsThis(i18nc("@info:whatsthis", "Check to include file alarms in the search."));
00160 grid->addWidget(mFileType, 3, 2);
00161
00162 mCommandType = new QCheckBox(i18nc("@option:check Alarm action", "Command"), group);
00163 mCommandType->setFixedSize(mCommandType->sizeHint());
00164 mCommandType->setWhatsThis(i18nc("@info:whatsthis", "Check to include command alarms in the search."));
00165 grid->addWidget(mCommandType, 4, 0);
00166
00167 mEmailType = new QCheckBox(i18nc("@option:check Alarm action", "Email"), group);
00168 mEmailType->setFixedSize(mEmailType->sizeHint());
00169 mEmailType->setWhatsThis(i18nc("@info:whatsthis", "Check to include email alarms in the search."));
00170 grid->addWidget(mEmailType, 4, 2);
00171
00172
00173 mLive->setChecked(mOptions & FIND_LIVE);
00174 mArchived->setChecked(mOptions & FIND_ARCHIVED);
00175 mMessageType->setChecked(mOptions & FIND_MESSAGE);
00176 mFileType->setChecked(mOptions & FIND_FILE);
00177 mCommandType->setChecked(mOptions & FIND_COMMAND);
00178 mEmailType->setChecked(mOptions & FIND_EMAIL);
00179
00180 connect(mDialog, SIGNAL(okClicked()), this, SLOT(slotFind()));
00181 }
00182
00183
00184 if (noArchived)
00185 {
00186 mLive->hide();
00187 mArchived->hide();
00188 mActiveArchivedSep->hide();
00189 }
00190 else
00191 {
00192 mLive->show();
00193 mArchived->show();
00194 mActiveArchivedSep->show();
00195 }
00196
00197
00198 bool live = false;
00199 bool archived = false;
00200 bool text = false;
00201 bool file = false;
00202 bool command = false;
00203 bool email = false;
00204 int rowCount = mListView->model()->rowCount();
00205 for (int row = 0; row < rowCount; ++row)
00206 {
00207 const KAEvent* event = mListView->event(row);
00208 if (event->expired())
00209 archived = true;
00210 else
00211 live = true;
00212 switch (event->action())
00213 {
00214 case KAEvent::MESSAGE: text = true; break;
00215 case KAEvent::FILE: file = true; break;
00216 case KAEvent::COMMAND: command = true; break;
00217 case KAEvent::EMAIL: email = true; break;
00218 }
00219 }
00220 mLive->setEnabled(live);
00221 mArchived->setEnabled(archived);
00222 mMessageType->setEnabled(text);
00223 mFileType->setEnabled(file);
00224 mCommandType->setEnabled(command);
00225 mEmailType->setEnabled(email);
00226
00227 mDialog->setHasCursor(mListView->selectionModel()->currentIndex().isValid());
00228 mDialog->show();
00229 }
00230
00231
00232
00233
00234 void Find::slotFind()
00235 {
00236 if (!mDialog)
00237 return;
00238 mHistory = mDialog->findHistory();
00239 mOptions = mDialog->options() & ~FIND_KALARM_OPTIONS;
00240 mOptions |= (mLive->isEnabled() && mLive->isChecked() ? FIND_LIVE : 0)
00241 | (mArchived->isEnabled() && mArchived->isChecked() ? FIND_ARCHIVED : 0)
00242 | (mMessageType->isEnabled() && mMessageType->isChecked() ? FIND_MESSAGE : 0)
00243 | (mFileType->isEnabled() && mFileType->isChecked() ? FIND_FILE : 0)
00244 | (mCommandType->isEnabled() && mCommandType->isChecked() ? FIND_COMMAND : 0)
00245 | (mEmailType->isEnabled() && mEmailType->isChecked() ? FIND_EMAIL : 0);
00246 if (!(mOptions & (FIND_LIVE | FIND_ARCHIVED))
00247 || !(mOptions & (FIND_MESSAGE | FIND_FILE | FIND_COMMAND | FIND_EMAIL)))
00248 {
00249 KMessageBox::sorry(mDialog, i18nc("@info", "No alarm types are selected to search"));
00250 return;
00251 }
00252
00253
00254 long options = mOptions & (KFind::WholeWordsOnly | KFind::CaseSensitive | KFind::RegularExpression);
00255 bool newFind = !mFind;
00256 bool newPattern = (mDialog->pattern() != mLastPattern);
00257 mLastPattern = mDialog->pattern();
00258 if (mFind)
00259 {
00260 mFind->resetCounts();
00261 mFind->setPattern(mLastPattern);
00262 mFind->setOptions(options);
00263 }
00264 else
00265 {
00266 mFind = new KFind(mLastPattern, options, mListView, mDialog);
00267 connect(mFind, SIGNAL(destroyed()), SLOT(slotKFindDestroyed()));
00268 mFind->closeFindNextDialog();
00269 }
00270
00271
00272 mStartID.clear();
00273 mNoCurrentItem = newPattern;
00274 bool checkEnd = false;
00275 if (newPattern)
00276 {
00277 mFound = false;
00278 if (mOptions & KFind::FromCursor)
00279 {
00280 QModelIndex index = mListView->selectionModel()->currentIndex();
00281 if (index.isValid())
00282 {
00283 mStartID = mListView->event(index)->id();
00284 mNoCurrentItem = false;
00285 checkEnd = true;
00286 }
00287 }
00288 }
00289
00290
00291 findNext(true, checkEnd, false);
00292 if (mFind && newFind)
00293 emit active(true);
00294 }
00295
00296
00297
00298
00299
00300
00301 void Find::findNext(bool forward, bool checkEnd, bool fromCurrent)
00302 {
00303 QModelIndex index;
00304 if (!mNoCurrentItem)
00305 index = mListView->selectionModel()->currentIndex();
00306 if (!fromCurrent)
00307 index = nextItem(index, forward);
00308
00309
00310 bool found = false;
00311 bool last = false;
00312 for ( ; index.isValid() && !last; index = nextItem(index, forward))
00313 {
00314 const KAEvent* event = mListView->event(index);
00315 if (!fromCurrent && !mStartID.isNull() && mStartID == event->id())
00316 last = true;
00317 fromCurrent = false;
00318 bool live = !event->expired();
00319 if ((live && !(mOptions & FIND_LIVE))
00320 || (!live && !(mOptions & FIND_ARCHIVED)))
00321 continue;
00322 switch (event->action())
00323 {
00324 case KAEvent::MESSAGE:
00325 if (!(mOptions & FIND_MESSAGE))
00326 break;
00327 mFind->setData(event->cleanText());
00328 found = (mFind->find() == KFind::Match);
00329 break;
00330
00331 case KAEvent::FILE:
00332 if (!(mOptions & FIND_FILE))
00333 break;
00334 mFind->setData(event->cleanText());
00335 found = (mFind->find() == KFind::Match);
00336 break;
00337
00338 case KAEvent::COMMAND:
00339 if (!(mOptions & FIND_COMMAND))
00340 break;
00341 mFind->setData(event->cleanText());
00342 found = (mFind->find() == KFind::Match);
00343 break;
00344
00345 case KAEvent::EMAIL:
00346 if (!(mOptions & FIND_EMAIL))
00347 break;
00348 mFind->setData(event->emailAddresses(", "));
00349 found = (mFind->find() == KFind::Match);
00350 if (found)
00351 break;
00352 mFind->setData(event->emailSubject());
00353 found = (mFind->find() == KFind::Match);
00354 if (found)
00355 break;
00356 mFind->setData(event->emailAttachments().join(", "));
00357 found = (mFind->find() == KFind::Match);
00358 if (found)
00359 break;
00360 mFind->setData(event->cleanText());
00361 found = (mFind->find() == KFind::Match);
00362 break;
00363 }
00364 if (found)
00365 break;
00366 }
00367
00368
00369 mNoCurrentItem = !index.isValid();
00370 if (found)
00371 {
00372
00373 mFound = true;
00374 QItemSelectionModel* sel = mListView->selectionModel();
00375 sel->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
00376 sel->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
00377 mListView->scrollTo(index);
00378 }
00379 else
00380 {
00381
00382 if (mFound || checkEnd)
00383 {
00384 QString msg = forward ? i18nc("@info", "<para>End of alarm list reached.</para><para>Continue from the beginning?</para>")
00385 : i18nc("@info", "<para>Beginning of alarm list reached.</para><para>Continue from the end?</para>");
00386 if (KMessageBox::questionYesNo(mListView, msg, QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel()) == KMessageBox::Yes)
00387 {
00388 mNoCurrentItem = true;
00389 findNext(forward, false, false);
00390 return;
00391 }
00392 }
00393 else
00394 mFind->displayFinalDialog();
00395 mNoCurrentItem = false;
00396 }
00397 }
00398
00399
00400
00401
00402 QModelIndex Find::nextItem(const QModelIndex& index, bool forward) const
00403 {
00404 if (mOptions & KFind::FindBackwards)
00405 forward = !forward;
00406 if (!index.isValid())
00407 {
00408 QAbstractItemModel* model = mListView->model();
00409 if (forward)
00410 return model->index(0, 0);
00411 else
00412 return model->index(model->rowCount() - 1, 0);
00413 }
00414 if (forward)
00415 return mListView->indexBelow(index);
00416 else
00417 return mListView->indexAbove(index);
00418 }