Mailcommon

searchpatternedit.cpp
1/*
2
3 SPDX-FileCopyrightText: Marc Mutz <mutz@kde.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6*/
7
8#include "searchpatternedit.h"
9#include "widgethandler/rulewidgethandlermanager.h"
11#include "mailcommon_debug.h"
12
13#include <KComboBox>
14#include <KLazyLocalizedString>
15#include <KLineEditEventHandler>
16#include <KLocalizedString>
17#include <QButtonGroup>
18#include <QFormLayout>
19#include <QHBoxLayout>
20#include <QIcon>
21#include <QLineEdit>
22#include <QPushButton>
23#include <QRadioButton>
24#include <QStackedWidget>
25// Definition of special rule field strings
26// Note: Also see SearchRule::matches() and ruleFieldToEnglish() if
27// you change the following i18n-ized strings!
28// Note: The index of the values in the following array has to correspond to
29// the value of the entries in the enum in SearchRuleWidget.
30
31using namespace MailCommon;
32
33static const struct {
34 const char *internalName;
35 const KLazyLocalizedString displayName;
36
37 [[nodiscard]] QString getLocalizedDisplayName() const
38 {
39 return displayName.toString();
40 }
41} SpecialRuleFields[] = {{"<message>", kli18n("Complete Message")},
42 {"<body>", kli18n("Body of Message")},
43 {"<any header>", kli18n("Anywhere in Headers")},
44 {"<recipients>", kli18n("All Recipients")},
45 {"<size>", kli18n("Size in Bytes")},
46 {"<age in days>", kli18n("Age in Days")},
47 {"<status>", kli18n("Message Status")},
48 {"<tag>", kli18n("Message Tag")},
49 {"Subject", kli18n("Subject")},
50 {"From", kli18n("From")},
51 {"To", kli18n("To")},
52 {"CC", kli18n("CC")},
53 {"Reply-To", kli18n("Reply To")},
54 {"Organization", kli18n("Organization")},
55 {"<date>", kli18n("Date")},
56 {"<encryption>", kli18n("Encryption")}};
57static const int SpecialRuleFieldsCount = sizeof(SpecialRuleFields) / sizeof(*SpecialRuleFields);
58
59//=============================================================================
60//
61// class SearchRuleWidget
62//
63//=============================================================================
64
66 SearchRule::Ptr aRule,
68 SearchPatternEdit::SearchModeType modeType)
69 : QWidget(parent)
70{
71 initFieldList(options);
72 initWidget(modeType);
73
74 if (aRule) {
75 setRule(aRule);
76 } else {
77 reset();
78 }
79}
80
81void SearchRuleWidget::setPatternEditOptions(SearchPatternEdit::SearchPatternEditOptions options)
82{
83 SearchRule::Ptr srule = rule();
84 QByteArray currentText = srule->field();
85
86 initFieldList(options);
87
88 mRuleField->clear();
89 mRuleField->addItems(mFilterFieldList);
90 KCompletion *comp = mRuleField->completionObject();
91 comp->clear();
92 comp->insertItems(mFilterFieldList);
93 mRuleField->setMaxCount(mRuleField->count());
94 mRuleField->adjustSize();
95
96 const bool headersOnly = (options & MailCommon::SearchPatternEdit::HeadersOnly);
97 const bool notShowSize = (options & MailCommon::SearchPatternEdit::NotShowSize);
98 const bool notShowDate = (options & MailCommon::SearchPatternEdit::NotShowDate);
99 const bool notShowAbsoluteDates = (options & MailCommon::SearchPatternEdit::NotShowAbsoluteDate);
100 const bool notShowTags = (options & MailCommon::SearchPatternEdit::NotShowTags);
101
102 if (headersOnly && (currentText != "<message>") && (currentText != "<body>")) {
103 mRuleField->setItemText(0, QString::fromLatin1(currentText));
104 } else {
105 mRuleField->setItemText(0, QString());
106 }
107
108 if (notShowSize && (currentText != "<size>")) {
109 mRuleField->setItemText(0, QString::fromLatin1(currentText));
110 } else {
111 mRuleField->setItemText(0, QString());
112 }
113
114 if (notShowDate && (currentText != "<date>")) {
115 mRuleField->setItemText(0, QString::fromLatin1(currentText));
116 } else {
117 mRuleField->setItemText(0, QString());
118 }
119
120 if (notShowAbsoluteDates && (currentText != "<age in days>")) {
121 mRuleField->setItemText(0, QString::fromLatin1(currentText));
122 } else {
123 mRuleField->setItemText(0, QString());
124 }
125 if (notShowTags && (currentText != "<tag>")) {
126 mRuleField->setItemText(0, QString::fromLatin1(currentText));
127 } else {
128 mRuleField->setItemText(0, QString());
129 }
130}
131
132void SearchRuleWidget::initWidget(SearchPatternEdit::SearchModeType modeType)
133{
134 auto hlay = new QHBoxLayout(this);
135 hlay->setContentsMargins({});
136
137 // initialize the header field combo box
138 mRuleField = new KComboBox(this);
139 mRuleField->setMinimumWidth(50);
140 mRuleField->setObjectName(QLatin1StringView("mRuleField"));
141 mRuleField->setEditable(true);
142 auto edit = new QLineEdit;
144 edit->setPlaceholderText(i18n("Choose or type your own criteria"));
145 mRuleField->setToolTip(i18n("Choose or type your own criteria"));
146 edit->setClearButtonEnabled(true);
147 mRuleField->setLineEdit(edit);
148
149 mRuleField->addItems(mFilterFieldList);
150 KCompletion *comp = mRuleField->completionObject();
151 comp->setIgnoreCase(true);
152 comp->insertItems(mFilterFieldList);
154
155 // don't show sliders when popping up this menu
156 mRuleField->setMaxCount(mRuleField->count());
157 mRuleField->adjustSize();
158 hlay->addWidget(mRuleField);
159
160 // initialize the function/value widget stack
161 mFunctionStack = new QStackedWidget(this);
162 // Don't expand the widget in vertical direction
164
165 hlay->addWidget(mFunctionStack);
166
167 mValueStack = new QStackedWidget(this);
168 hlay->addWidget(mValueStack);
169 hlay->setStretchFactor(mValueStack, 10);
170
171 mAdd = new QPushButton(this);
172 mAdd->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
174 hlay->addWidget(mAdd);
175
176 mRemove = new QPushButton(this);
177 mRemove->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
179 hlay->addWidget(mRemove);
180
181 RuleWidgetHandlerManager::instance()->setIsAkonadiSearch(modeType == SearchPatternEdit::BalooMode);
182
183 RuleWidgetHandlerManager::instance()->createWidgets(mFunctionStack, mValueStack, this);
184
185 // redirect focus to the header field combo box
186 setFocusProxy(mRuleField);
187
188 connect(mRuleField, &QComboBox::textActivated, this, &SearchRuleWidget::slotRuleFieldChanged);
189 connect(mRuleField, &QComboBox::editTextChanged, this, &SearchRuleWidget::slotRuleFieldChanged);
191
192 connect(mAdd, &QAbstractButton::clicked, this, &SearchRuleWidget::slotAddWidget);
193 connect(mRemove, &QAbstractButton::clicked, this, &SearchRuleWidget::slotRemoveWidget);
194}
195
196void SearchRuleWidget::updateAddRemoveButton(bool addButtonEnabled, bool removeButtonEnabled)
197{
198 mAdd->setEnabled(addButtonEnabled);
199 mRemove->setEnabled(removeButtonEnabled);
200}
201
202void SearchRuleWidget::slotAddWidget()
203{
204 Q_EMIT addWidget(this);
205}
206
207void SearchRuleWidget::slotRemoveWidget()
208{
209 Q_EMIT removeWidget(this);
210}
211
213{
214 Q_ASSERT(aRule);
215
216 qCDebug(MAILCOMMON_LOG) << "(" << aRule->asString() << ")";
217
218 //--------------set the field
219 int i = indexOfRuleField(aRule->field());
220
221 mRuleField->blockSignals(true);
222
223 if (i < 0) { // not found -> user defined field
224 mRuleField->setItemText(0, QString::fromLatin1(aRule->field()));
225 i = 0;
226 } else { // found in the list of predefined fields
227 mRuleField->setItemText(0, QString());
228 }
229
230 mRuleField->setCurrentIndex(i);
231 mRuleField->blockSignals(false);
232
233 RuleWidgetHandlerManager::instance()->setRule(mFunctionStack, mValueStack, aRule);
234}
235
237{
238 const QByteArray ruleField = ruleFieldToEnglish(mRuleField->currentText());
239
240 const SearchRule::Function function = RuleWidgetHandlerManager::instance()->function(ruleField, mFunctionStack);
241
242 const QString value = RuleWidgetHandlerManager::instance()->value(ruleField, mFunctionStack, mValueStack);
243
244 return SearchRule::createInstance(ruleField, function, value);
245}
246
248{
249 mRuleField->blockSignals(true);
250 mRuleField->setItemText(0, QString());
251 mRuleField->setCurrentIndex(0);
252 mRuleField->blockSignals(false);
253
254 RuleWidgetHandlerManager::instance()->reset(mFunctionStack, mValueStack);
255}
256
257void SearchRuleWidget::slotFunctionChanged()
258{
259 const QByteArray ruleField = ruleFieldToEnglish(mRuleField->currentText());
260 RuleWidgetHandlerManager::instance()->update(ruleField, mFunctionStack, mValueStack);
261 const QString prettyValue = RuleWidgetHandlerManager::instance()->prettyValue(ruleField, mFunctionStack, mValueStack);
262
263 Q_EMIT contentsChanged(prettyValue);
264}
265
266void SearchRuleWidget::slotValueChanged()
267{
268 const QByteArray ruleField = ruleFieldToEnglish(mRuleField->currentText());
269
270 const QString prettyValue = RuleWidgetHandlerManager::instance()->prettyValue(ruleField, mFunctionStack, mValueStack);
271
272 Q_EMIT contentsChanged(prettyValue);
273}
274
275void SearchRuleWidget::slotReturnPressed()
276{
277 Q_EMIT returnPressed();
278}
279
281{
282 for (int i = 0; i < SpecialRuleFieldsCount; ++i) {
283 if (i18nVal == SpecialRuleFields[i].getLocalizedDisplayName()) {
284 return SpecialRuleFields[i].internalName;
285 }
286 }
287 return i18nVal.toLatin1();
288}
289
290int SearchRuleWidget::ruleFieldToId(const QString &i18nVal)
291{
292 for (int i = 0; i < SpecialRuleFieldsCount; ++i) {
293 if (i18nVal == SpecialRuleFields[i].getLocalizedDisplayName()) {
294 return i;
295 }
296 }
297 return -1; // no pseudo header
298}
299
300static QString displayNameFromInternalName(const QString &internal)
301{
302 for (int i = 0; i < SpecialRuleFieldsCount; ++i) {
303 if (internal == QLatin1StringView(SpecialRuleFields[i].internalName)) {
304 return SpecialRuleFields[i].getLocalizedDisplayName();
305 }
306 }
307 return QLatin1StringView(internal.toLatin1());
308}
309
311{
312 if (aName.isEmpty()) {
313 return -1;
314 }
315
316 const QString i18n_aName = displayNameFromInternalName(QLatin1StringView(aName));
317 const int nbRuleField = mRuleField->count();
318 for (int i = 1; i < nbRuleField; ++i) {
319 if (mRuleField->itemText(i) == i18n_aName) {
320 return i;
321 }
322 }
323
324 return -1;
325}
326
327void SearchRuleWidget::initFieldList(SearchPatternEdit::SearchPatternEditOptions options)
328{
329 const bool headersOnly = (options & MailCommon::SearchPatternEdit::HeadersOnly);
330 const bool notShowAbsoluteDates = (options & MailCommon::SearchPatternEdit::NotShowAbsoluteDate);
331 const bool notShowSize = (options & MailCommon::SearchPatternEdit::NotShowSize);
332 const bool notShowDate = (options & MailCommon::SearchPatternEdit::NotShowDate);
333 const bool notShowTags = (options & MailCommon::SearchPatternEdit::NotShowTags);
334
335 mFilterFieldList.clear();
336 mFilterFieldList.append(QString()); // empty entry for user input
337
338 if (!headersOnly) {
339 mFilterFieldList.append(SpecialRuleFields[Message].getLocalizedDisplayName());
340 mFilterFieldList.append(SpecialRuleFields[Body].getLocalizedDisplayName());
341 }
342 mFilterFieldList.append(SpecialRuleFields[AnyHeader].getLocalizedDisplayName());
343 mFilterFieldList.append(SpecialRuleFields[Recipients].getLocalizedDisplayName());
344 if (!notShowSize) {
345 mFilterFieldList.append(SpecialRuleFields[Size].getLocalizedDisplayName());
346 }
347 if (!notShowAbsoluteDates) {
348 mFilterFieldList.append(SpecialRuleFields[AgeInDays].getLocalizedDisplayName());
349 }
350
351 mFilterFieldList.append(SpecialRuleFields[Subject].getLocalizedDisplayName());
352 mFilterFieldList.append(SpecialRuleFields[From].getLocalizedDisplayName());
353 mFilterFieldList.append(SpecialRuleFields[To].getLocalizedDisplayName());
354 mFilterFieldList.append(SpecialRuleFields[CC].getLocalizedDisplayName());
355 mFilterFieldList.append(SpecialRuleFields[Status].getLocalizedDisplayName());
356 if (!notShowTags) {
357 mFilterFieldList.append(SpecialRuleFields[Tag].getLocalizedDisplayName());
358 }
359 mFilterFieldList.append(SpecialRuleFields[ReplyTo].getLocalizedDisplayName());
360 mFilterFieldList.append(SpecialRuleFields[Organization].getLocalizedDisplayName());
361
362 if (!notShowDate) {
363 mFilterFieldList.append(SpecialRuleFields[Date].getLocalizedDisplayName());
364 }
365
366 mFilterFieldList.append(SpecialRuleFields[Encryption].getLocalizedDisplayName());
367
368 // these others only represent message headers and you can add to
369 // them as you like
370 mFilterFieldList.append(QStringLiteral("List-Id"));
371 mFilterFieldList.append(QStringLiteral("Resent-From"));
372 mFilterFieldList.append(QStringLiteral("X-Loop"));
373 mFilterFieldList.append(QStringLiteral("X-Mailing-List"));
374 mFilterFieldList.append(QStringLiteral("X-Spam-Flag"));
375 mFilterFieldList.append(QStringLiteral("X-Spam-Status"));
376}
377
378void SearchRuleWidget::slotRuleFieldChanged(const QString &field)
379{
380 RuleWidgetHandlerManager::instance()->update(ruleFieldToEnglish(field), mFunctionStack, mValueStack);
381}
382
383//=============================================================================
384//
385// class KMFilterActionWidgetLister (the filter action editor)
386//
387//=============================================================================
388
389SearchRuleWidgetLister::SearchRuleWidgetLister(QWidget *parent, SearchPatternEdit::SearchPatternEditOptions options, SearchPatternEdit::SearchModeType modeType)
390 : KWidgetLister(false, 1, SearchPattern::filterRulesMaximumSize(), parent)
391{
392 mRuleList = nullptr;
393
394 mTypeMode = modeType;
395 mOptions = options;
396}
397
398SearchRuleWidgetLister::~SearchRuleWidgetLister() = default;
399
400void SearchRuleWidgetLister::setPatternEditOptions(SearchPatternEdit::SearchPatternEditOptions options)
401{
402 mOptions = options;
403 const auto lst = widgets();
404 for (QWidget *w : lst) {
405 qobject_cast<SearchRuleWidget *>(w)->setPatternEditOptions(options);
406 }
407}
408
409void SearchRuleWidgetLister::setRuleList(QList<SearchRule::Ptr> *aList)
410{
411 Q_ASSERT(aList);
412
413 if (mRuleList && mRuleList != aList) {
414 regenerateRuleListFromWidgets();
415 }
416
417 mRuleList = aList;
418
419 if (!widgets().isEmpty()) { // move this below next 'if'?
420 widgets().constFirst()->blockSignals(true);
421 }
422
423 if (aList->isEmpty()) {
424 slotClear();
425 widgets().constFirst()->blockSignals(false);
426 return;
427 }
428
429 int superfluousItems = (int)mRuleList->count() - widgetsMaximum();
430 if (superfluousItems > 0) {
431 qCDebug(MAILCOMMON_LOG) << "Clipping rule list to" << widgetsMaximum() << "items!";
432
433 for (; superfluousItems; superfluousItems--) {
434 mRuleList->removeLast();
435 }
436 }
437
438 // set the right number of widgets
439 setNumberOfShownWidgetsTo(qMax((int)mRuleList->count(), widgetsMinimum()));
440
441 // load the actions into the widgets
442 QList<QWidget *> widgetList = widgets();
446 QList<QWidget *>::const_iterator wItEnd = widgetList.constEnd();
447 for (rIt = mRuleList->constBegin(); rIt != rItEnd && wIt != wItEnd; ++rIt, ++wIt) {
448 qobject_cast<SearchRuleWidget *>(*wIt)->setRule((*rIt));
449 }
450 for (; wIt != wItEnd; ++wIt) {
451 qobject_cast<SearchRuleWidget *>(*wIt)->reset();
452 }
453
454 Q_ASSERT(!widgets().isEmpty());
455 widgets().constFirst()->blockSignals(false);
456 updateAddRemoveButton();
457}
458
459void SearchRuleWidgetLister::slotAddWidget(QWidget *w)
460{
462 updateAddRemoveButton();
463}
464
465void SearchRuleWidgetLister::slotRemoveWidget(QWidget *w)
466{
467 removeWidget(w);
468 updateAddRemoveButton();
469}
470
471void SearchRuleWidgetLister::reconnectWidget(SearchRuleWidget *w)
472{
473 connect(w, &SearchRuleWidget::addWidget, this, &SearchRuleWidgetLister::slotAddWidget, Qt::UniqueConnection);
474 connect(w, &SearchRuleWidget::removeWidget, this, &SearchRuleWidgetLister::slotRemoveWidget, Qt::UniqueConnection);
475}
476
477void SearchRuleWidgetLister::updateAddRemoveButton()
478{
479 QList<QWidget *> widgetList = widgets();
480 const int numberOfWidget(widgetList.count());
481 bool addButtonEnabled = false;
482 bool removeButtonEnabled = false;
483 if (numberOfWidget <= widgetsMinimum()) {
484 addButtonEnabled = true;
485 removeButtonEnabled = false;
486 } else if (numberOfWidget >= widgetsMaximum()) {
487 addButtonEnabled = false;
488 removeButtonEnabled = true;
489 } else {
490 addButtonEnabled = true;
491 removeButtonEnabled = true;
492 }
494 QList<QWidget *>::ConstIterator wEnd = widgetList.constEnd();
495 for (; wIt != wEnd; ++wIt) {
496 auto w = qobject_cast<SearchRuleWidget *>(*wIt);
497 w->updateAddRemoveButton(addButtonEnabled, removeButtonEnabled);
498 }
499}
500
501void SearchRuleWidgetLister::reset()
502{
503 if (mRuleList) {
504 regenerateRuleListFromWidgets();
505 }
506
507 mRuleList = nullptr;
508 slotClear();
509 updateAddRemoveButton();
510}
511
512QWidget *SearchRuleWidgetLister::createWidget(QWidget *parent)
513{
514 auto w = new SearchRuleWidget(parent, SearchRule::Ptr(), mOptions, mTypeMode);
515 reconnectWidget(w);
516 return w;
517}
518
519void SearchRuleWidgetLister::clearWidget(QWidget *aWidget)
520{
521 if (aWidget) {
522 auto w = static_cast<SearchRuleWidget *>(aWidget);
523 w->reset();
524 reconnectWidget(w);
525 updateAddRemoveButton();
526 }
527}
528
529void SearchRuleWidgetLister::regenerateRuleListFromWidgets()
530{
531 if (!mRuleList) {
532 return;
533 }
534
535 mRuleList->clear();
536
537 const auto lst = widgets();
538 for (const QWidget *w : lst) {
539 SearchRule::Ptr r = qobject_cast<const SearchRuleWidget *>(w)->rule();
540 if (r && !r->isEmpty()) {
541 mRuleList->append(r);
542 }
543 }
544 updateAddRemoveButton();
545}
546
547//=============================================================================
548//
549// class SearchPatternEdit
550//
551//=============================================================================
552
553SearchPatternEdit::SearchPatternEdit(QWidget *parent, SearchPatternEditOptions options, SearchModeType modeType)
554 : QWidget(parent)
555{
557 setObjectName(QLatin1StringView("SearchPatternEdit"));
558 initLayout(options, modeType);
559}
560
561SearchPatternEdit::~SearchPatternEdit() = default;
562
563void SearchPatternEdit::updateSearchPattern()
564{
565 mRuleLister->regenerateRuleListFromWidgets();
566}
567
568void SearchPatternEdit::setPatternEditOptions(SearchPatternEdit::SearchPatternEditOptions options)
569{
570 mRuleLister->setPatternEditOptions(options);
571}
572
573void SearchPatternEdit::initLayout(SearchPatternEditOptions options, SearchModeType modeType)
574{
575 auto layout = new QFormLayout(this);
577
578 const bool matchAllMessages = (options & MailCommon::SearchPatternEdit::MatchAllMessages);
579 //------------the radio buttons
580 mAllRBtn = new QRadioButton(i18n("Match a&ll of the following"), this);
581 mAnyRBtn = new QRadioButton(i18n("Match an&y of the following"), this);
582 if (matchAllMessages) {
583 mAllMessageRBtn = new QRadioButton(i18n("Match all messages"), this);
584 }
585
586 mAllRBtn->setObjectName(QLatin1StringView("mAllRBtn"));
587 mAllRBtn->setChecked(true);
588 mAnyRBtn->setObjectName(QLatin1StringView("mAnyRBtn"));
589 mAnyRBtn->setChecked(false);
590 if (matchAllMessages) {
591 mAllMessageRBtn->setObjectName(QLatin1StringView("mAllMessageRBtn"));
592 mAllMessageRBtn->setChecked(false);
593 }
594 layout->addRow(i18n("Filter criteria:"), mAllRBtn);
595 layout->addRow(QString(), mAnyRBtn);
596 if (matchAllMessages) {
597 layout->addRow(QString(), mAllMessageRBtn);
598 }
599
600 auto bg = new QButtonGroup(this);
601 bg->addButton(mAllRBtn);
602 bg->addButton(mAnyRBtn);
603 if (matchAllMessages) {
604 bg->addButton(mAllMessageRBtn);
605 }
606
607 //------------connect a few signals
608 connect(bg, &QButtonGroup::buttonClicked, this, &SearchPatternEdit::slotRadioClicked);
609
610 //------------the list of SearchRuleWidget's
611 mRuleLister = new SearchRuleWidgetLister(this, options, modeType);
612
613 mRuleLister->slotClear();
614
615 if (!mRuleLister->widgets().isEmpty()) {
616 const int numberOfWidget(mRuleLister->widgets().count());
617 for (int i = 0; i < numberOfWidget; ++i) {
618 SearchRuleWidget *srw = static_cast<SearchRuleWidget *>(mRuleLister->widgets().at(i));
619 connect(srw, &SearchRuleWidget::fieldChanged, this, &SearchPatternEdit::slotAutoNameHack);
620 connect(srw, &SearchRuleWidget::contentsChanged, this, &SearchPatternEdit::slotAutoNameHack);
621 connect(srw, &SearchRuleWidget::returnPressed, this, &SearchPatternEdit::returnPressed);
622 }
623 } else {
624 qCDebug(MAILCOMMON_LOG) << "No first SearchRuleWidget, though slotClear() has been called!";
625 }
626
627 connect(mRuleLister, qOverload<QWidget *>(&SearchRuleWidgetLister::widgetAdded), this, &SearchPatternEdit::slotRuleAdded);
628 connect(mRuleLister, qOverload<>(&SearchRuleWidgetLister::widgetRemoved), this, &SearchPatternEdit::patternChanged);
629 connect(mRuleLister, &KPIM::KWidgetLister::clearWidgets, this, &SearchPatternEdit::patternChanged);
630
631 layout->addRow(mRuleLister);
632}
633
634void SearchPatternEdit::setSearchPattern(SearchPattern *aPattern)
635{
636 Q_ASSERT(aPattern);
637
638 mRuleLister->setRuleList(aPattern);
639
640 mPattern = aPattern;
641
642 blockSignals(true);
643 if (mPattern->op() == SearchPattern::OpOr) {
644 mAnyRBtn->setChecked(true);
645 } else if (mPattern->op() == SearchPattern::OpAnd) {
646 mAllRBtn->setChecked(true);
647 } else if (mAllMessageRBtn && (mPattern->op() == SearchPattern::OpAll)) {
648 mAllMessageRBtn->setChecked(true);
649 }
650 mRuleLister->setEnabled(mPattern->op() != SearchPattern::OpAll);
651 blockSignals(false);
652
653 setEnabled(true);
654 Q_EMIT patternChanged();
655}
656
657void SearchPatternEdit::reset()
658{
659 mRuleLister->reset();
660
661 blockSignals(true);
662 mAllRBtn->setChecked(true);
663 blockSignals(false);
664
665 setEnabled(false);
666 Q_EMIT patternChanged();
667}
668
669void SearchPatternEdit::slotRadioClicked(QAbstractButton *aRBtn)
670{
671 if (mPattern) {
672 if (aRBtn == mAllRBtn) {
673 mPattern->setOp(SearchPattern::OpAnd);
674 } else if (aRBtn == mAnyRBtn) {
675 mPattern->setOp(SearchPattern::OpOr);
676 } else if (aRBtn == mAllMessageRBtn) {
677 mPattern->setOp(SearchPattern::OpAll);
678 }
679 mRuleLister->setEnabled(mPattern->op() != SearchPattern::OpAll);
680 Q_EMIT patternChanged();
681 }
682}
683
684void SearchPatternEdit::slotAutoNameHack()
685{
686 mRuleLister->regenerateRuleListFromWidgets();
687 Q_EMIT maybeNameChanged();
688 Q_EMIT patternChanged();
689}
690
691void SearchPatternEdit::slotRuleAdded(QWidget *newRuleWidget)
692{
693 auto srw = static_cast<SearchRuleWidget *>(newRuleWidget);
694 connect(srw, &SearchRuleWidget::fieldChanged, this, &SearchPatternEdit::slotAutoNameHack);
695 connect(srw, &SearchRuleWidget::contentsChanged, this, &SearchPatternEdit::slotAutoNameHack);
696 connect(srw, &SearchRuleWidget::returnPressed, this, &SearchPatternEdit::returnPressed);
697 Q_EMIT patternChanged();
698}
699
700#include "moc_searchpatternedit.cpp"
void setEditable(bool editable)
virtual void setLineEdit(QLineEdit *)
KCompletion * completionObject(bool handleSignals=true)
void insertItems(const QStringList &items)
virtual void setCompletionMode(CompletionMode mode)
virtual void setIgnoreCase(bool ignoreCase)
virtual void clear()
QString toString() const
virtual void addWidgetAfterThisWidget(QWidget *currentWidget, QWidget *widget=nullptr)
virtual void slotClear()
virtual void removeWidget(QWidget *widget)
int widgetsMaximum() const
virtual void setNumberOfShownWidgetsTo(int count)
QList< QWidget * > widgets() const
int widgetsMinimum() const
Singleton to manage the list of RuleWidgetHandlers.
This class is an abstraction of a search over messages.
void setOp(SearchPattern::Operator aOp)
Sets the filter operator.
SearchPattern::Operator op() const
Returns the filter operator.
A widget to edit a single MailCommon::SearchRule.
void reset()
Resets the rule currently worked on and updates the widget accordingly.
SearchRuleWidget(QWidget *parent=nullptr, MailCommon::SearchRule::Ptr aRule=MailCommon::SearchRule::Ptr(), SearchPatternEdit::SearchPatternEditOptions options=(SearchPatternEdit::SearchPatternEditOptions)(SearchPatternEdit::None), SearchPatternEdit::SearchModeType modeType=SearchPatternEdit::StandardMode)
Constructor.
void contentsChanged(const QString &)
This signal is emitted whenever the user alters the contents/value of the rule.
MailCommon::SearchRule::Ptr rule() const
Returns a reference to the currently-worked-on MailCommon::SearchRule.
void fieldChanged(const QString &)
This signal is emitted whenever the user alters the field.
int indexOfRuleField(const QByteArray &aName) const
Used internally to find the corresponding index into the field ComboBox.
void setRule(MailCommon::SearchRule::Ptr aRule)
Sets the rule.
static QByteArray ruleFieldToEnglish(const QString &i18nVal)
Used internally to translate i18n-ized pseudo-headers back to English.
std::shared_ptr< SearchRule > Ptr
Defines a pointer to a search rule.
Definition searchrule.h:29
Function
Describes operators for comparison of field and contents.
Definition searchrule.h:40
static SearchRule::Ptr createInstance(const QByteArray &field=QByteArray(), Function function=FuncContains, const QString &contents=QString())
Creates a new search rule of a certain type by instantiating the appropriate subclass depending on th...
QString i18n(const char *text, const TYPE &arg...)
void catchReturnKey(QObject *lineEdit)
The filter dialog.
void setChecked(bool)
void clicked(bool checked)
void setIcon(const QIcon &icon)
void buttonClicked(QAbstractButton *button)
bool isEmpty() const const
void addItems(const QStringList &texts)
void clear()
void setCurrentIndex(int index)
void editTextChanged(const QString &text)
QString itemText(int index) const const
void setMaxCount(int max)
void setItemText(int index, const QString &text)
void textActivated(const QString &text)
QIcon fromTheme(const QString &name)
void setContentsMargins(const QMargins &margins)
void append(QList< T > &&value)
void clear()
const_iterator constBegin() const const
const_iterator constEnd() const const
const T & constFirst() const const
qsizetype count() const const
bool isEmpty() const const
void removeLast()
Q_EMITQ_EMIT
bool blockSignals(bool block)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
void setObjectName(QAnyStringView name)
QString fromLatin1(QByteArrayView str)
QByteArray toLatin1() const const
UniqueConnection
void adjustSize()
void setEnabled(bool)
QLayout * layout() const const
void setMinimumWidth(int minw)
void setFocusProxy(QWidget *w)
void setSizePolicy(QSizePolicy)
void setToolTip(const QString &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:01 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.