8#include "searchpatternedit.h"
9#include "widgethandler/rulewidgethandlermanager.h"
11#include "mailcommon_debug.h"
14#include <KLazyLocalizedString>
15#include <KLineEditEventHandler>
16#include <KLocalizedString>
17#include <QButtonGroup>
23#include <QRadioButton>
24#include <QStackedWidget>
34 const char *internalName;
37 [[nodiscard]]
QString getLocalizedDisplayName()
const
39 return displayName.toString();
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")},
53 {
"Reply-To", kli18n(
"Reply To")},
54 {
"Organization", kli18n(
"Organization")},
55 {
"<date>", kli18n(
"Date")},
56 {
"<encryption>", kli18n(
"Encryption")},
57 {
"<attachment>", kli18n(
"Attachment")},
58 {
"<invitation>", kli18n(
"Invitation")}};
59static const int SpecialRuleFieldsCount =
sizeof(SpecialRuleFields) /
sizeof(*SpecialRuleFields);
69 SearchPatternEdit::SearchPatternEditOptions options,
70 SearchPatternEdit::SearchModeType modeType)
73 initFieldList(options);
83void SearchRuleWidget::setPatternEditOptions(SearchPatternEdit::SearchPatternEditOptions options)
88 initFieldList(options);
91 mRuleField->
addItems(mFilterFieldList);
98 const bool headersOnly = (options & MailCommon::SearchPatternEdit::HeadersOnly);
99 const bool notShowSize = (options & MailCommon::SearchPatternEdit::NotShowSize);
100 const bool notShowDate = (options & MailCommon::SearchPatternEdit::NotShowDate);
101 const bool notShowAbsoluteDates = (options & MailCommon::SearchPatternEdit::NotShowAbsoluteDate);
102 const bool notShowTags = (options & MailCommon::SearchPatternEdit::NotShowTags);
104 if (headersOnly && (currentText !=
"<message>") && (currentText !=
"<body>")) {
110 if (notShowSize && (currentText !=
"<size>")) {
113 mRuleField->setItemText(0, QString());
116 if (notShowDate && (currentText !=
"<date>")) {
119 mRuleField->setItemText(0, QString());
122 if (notShowAbsoluteDates && (currentText !=
"<age in days>")) {
125 mRuleField->setItemText(0, QString());
127 if (notShowTags && (currentText !=
"<tag>")) {
130 mRuleField->setItemText(0, QString());
134void SearchRuleWidget::initWidget(SearchPatternEdit::SearchModeType modeType)
136 auto hlay =
new QHBoxLayout(
this);
137 hlay->setContentsMargins({});
140 mRuleField =
new KComboBox(
this);
141 mRuleField->setMinimumWidth(50);
142 mRuleField->setObjectName(QLatin1StringView(
"mRuleField"));
143 mRuleField->setEditable(
true);
144 auto edit =
new QLineEdit;
146 edit->setPlaceholderText(
i18nc(
"@info:placeholder",
"Choose or type your own criteria"));
147 mRuleField->setToolTip(
i18nc(
"@info:tooltip",
"Choose or type your own criteria"));
148 edit->setClearButtonEnabled(
true);
149 mRuleField->setLineEdit(edit);
151 mRuleField->addItems(mFilterFieldList);
152 KCompletion *comp = mRuleField->completionObject();
158 mRuleField->setMaxCount(mRuleField->count());
159 mRuleField->adjustSize();
160 hlay->addWidget(mRuleField);
163 mFunctionStack =
new QStackedWidget(
this);
167 hlay->addWidget(mFunctionStack);
169 mValueStack =
new QStackedWidget(
this);
170 hlay->addWidget(mValueStack);
171 hlay->setStretchFactor(mValueStack, 10);
173 mAdd =
new QPushButton(
this);
176 hlay->addWidget(mAdd);
178 mRemove =
new QPushButton(
this);
181 hlay->addWidget(mRemove);
183 RuleWidgetHandlerManager::instance()->setIsAkonadiSearch(modeType == SearchPatternEdit::BalooMode);
185 RuleWidgetHandlerManager::instance()->createWidgets(mFunctionStack, mValueStack,
this);
198void SearchRuleWidget::updateAddRemoveButton(
bool addButtonEnabled,
bool removeButtonEnabled)
200 mAdd->setEnabled(addButtonEnabled);
201 mRemove->setEnabled(removeButtonEnabled);
204void SearchRuleWidget::slotAddWidget()
209void SearchRuleWidget::slotRemoveWidget()
211 Q_EMIT removeWidget(
this);
218 qCDebug(MAILCOMMON_LOG) <<
"(" << aRule->asString() <<
")";
223 mRuleField->blockSignals(
true);
229 mRuleField->setItemText(0,
QString());
232 mRuleField->setCurrentIndex(i);
233 mRuleField->blockSignals(
false);
235 RuleWidgetHandlerManager::instance()->setRule(mFunctionStack, mValueStack, aRule);
242 const SearchRule::Function function = RuleWidgetHandlerManager::instance()->function(ruleField, mFunctionStack);
244 const QString value = RuleWidgetHandlerManager::instance()->value(ruleField, mFunctionStack, mValueStack);
251 mRuleField->blockSignals(
true);
252 mRuleField->setItemText(0,
QString());
253 mRuleField->setCurrentIndex(0);
254 mRuleField->blockSignals(
false);
256 RuleWidgetHandlerManager::instance()->reset(mFunctionStack, mValueStack);
259void SearchRuleWidget::slotFunctionChanged()
262 RuleWidgetHandlerManager::instance()->update(ruleField, mFunctionStack, mValueStack);
263 const QString prettyValue = RuleWidgetHandlerManager::instance()->prettyValue(ruleField, mFunctionStack, mValueStack);
268void SearchRuleWidget::slotValueChanged()
272 const QString prettyValue = RuleWidgetHandlerManager::instance()->prettyValue(ruleField, mFunctionStack, mValueStack);
277void SearchRuleWidget::slotReturnPressed()
284 for (
int i = 0; i < SpecialRuleFieldsCount; ++i) {
285 if (i18nVal == SpecialRuleFields[i].getLocalizedDisplayName()) {
286 return SpecialRuleFields[i].internalName;
292int SearchRuleWidget::ruleFieldToId(
const QString &i18nVal)
294 for (
int i = 0; i < SpecialRuleFieldsCount; ++i) {
295 if (i18nVal == SpecialRuleFields[i].getLocalizedDisplayName()) {
302static QString displayNameFromInternalName(
const QString &internal)
304 for (
int i = 0; i < SpecialRuleFieldsCount; ++i) {
305 if (internal == QLatin1StringView(SpecialRuleFields[i].internalName)) {
306 return SpecialRuleFields[i].getLocalizedDisplayName();
309 return QLatin1StringView(internal.
toLatin1());
319 const int nbRuleField = mRuleField->count();
320 for (
int i = 1; i < nbRuleField; ++i) {
321 if (mRuleField->itemText(i) == i18n_aName) {
329void SearchRuleWidget::initFieldList(SearchPatternEdit::SearchPatternEditOptions options)
331 const bool headersOnly = (options & MailCommon::SearchPatternEdit::HeadersOnly);
332 const bool notShowAbsoluteDates = (options & MailCommon::SearchPatternEdit::NotShowAbsoluteDate);
333 const bool notShowSize = (options & MailCommon::SearchPatternEdit::NotShowSize);
334 const bool notShowDate = (options & MailCommon::SearchPatternEdit::NotShowDate);
335 const bool notShowTags = (options & MailCommon::SearchPatternEdit::NotShowTags);
337 mFilterFieldList.
clear();
341 mFilterFieldList.
append(SpecialRuleFields[Message].getLocalizedDisplayName());
342 mFilterFieldList.
append(SpecialRuleFields[Body].getLocalizedDisplayName());
344 mFilterFieldList.
append(SpecialRuleFields[AnyHeader].getLocalizedDisplayName());
345 mFilterFieldList.
append(SpecialRuleFields[Recipients].getLocalizedDisplayName());
347 mFilterFieldList.
append(SpecialRuleFields[Size].getLocalizedDisplayName());
349 if (!notShowAbsoluteDates) {
350 mFilterFieldList.append(SpecialRuleFields[AgeInDays].getLocalizedDisplayName());
353 mFilterFieldList.append(SpecialRuleFields[Subject].getLocalizedDisplayName());
354 mFilterFieldList.append(SpecialRuleFields[From].getLocalizedDisplayName());
355 mFilterFieldList.append(SpecialRuleFields[To].getLocalizedDisplayName());
356 mFilterFieldList.append(SpecialRuleFields[CC].getLocalizedDisplayName());
357 mFilterFieldList.append(SpecialRuleFields[Status].getLocalizedDisplayName());
359 mFilterFieldList.append(SpecialRuleFields[Tag].getLocalizedDisplayName());
361 mFilterFieldList.append(SpecialRuleFields[ReplyTo].getLocalizedDisplayName());
362 mFilterFieldList.append(SpecialRuleFields[Organization].getLocalizedDisplayName());
365 mFilterFieldList.append(SpecialRuleFields[Date].getLocalizedDisplayName());
368 mFilterFieldList.append(SpecialRuleFields[Encryption].getLocalizedDisplayName());
369 mFilterFieldList.append(SpecialRuleFields[Attachment].getLocalizedDisplayName());
370 mFilterFieldList.append(SpecialRuleFields[Invitation].getLocalizedDisplayName());
374 mFilterFieldList.append(QStringLiteral(
"List-Id"));
375 mFilterFieldList.append(QStringLiteral(
"Resent-From"));
376 mFilterFieldList.append(QStringLiteral(
"X-Loop"));
377 mFilterFieldList.append(QStringLiteral(
"X-Mailing-List"));
378 mFilterFieldList.append(QStringLiteral(
"X-Spam-Flag"));
379 mFilterFieldList.append(QStringLiteral(
"X-Spam-Status"));
382void SearchRuleWidget::slotRuleFieldChanged(
const QString &field)
384 RuleWidgetHandlerManager::instance()->update(
ruleFieldToEnglish(field), mFunctionStack, mValueStack);
393SearchRuleWidgetLister::SearchRuleWidgetLister(QWidget *parent, SearchPatternEdit::SearchPatternEditOptions options, SearchPatternEdit::SearchModeType modeType)
394 : KWidgetLister(false, 1,
SearchPattern::filterRulesMaximumSize(), parent)
398 mTypeMode = modeType;
402SearchRuleWidgetLister::~SearchRuleWidgetLister() =
default;
404void SearchRuleWidgetLister::setPatternEditOptions(SearchPatternEdit::SearchPatternEditOptions options)
413void SearchRuleWidgetLister::setRuleList(QList<SearchRule::Ptr> *aList)
417 if (mRuleList && mRuleList != aList) {
418 regenerateRuleListFromWidgets();
424 widgets().constFirst()->blockSignals(
true);
429 widgets().constFirst()->blockSignals(
false);
434 if (superfluousItems > 0) {
435 qCDebug(MAILCOMMON_LOG) <<
"Clipping rule list to" <<
widgetsMaximum() <<
"items!";
437 for (; superfluousItems; superfluousItems--) {
438 mRuleList->removeLast();
446 QList<QWidget *> widgetList =
widgets();
447 QList<SearchRule::Ptr>::const_iterator rIt;
448 QList<SearchRule::Ptr>::const_iterator rItEnd(mRuleList->constEnd());
449 QList<QWidget *>::const_iterator wIt = widgetList.
constBegin();
450 QList<QWidget *>::const_iterator wItEnd = widgetList.
constEnd();
451 for (rIt = mRuleList->constBegin(); rIt != rItEnd && wIt != wItEnd; ++rIt, ++wIt) {
454 for (; wIt != wItEnd; ++wIt) {
458 Q_ASSERT(!
widgets().isEmpty());
459 widgets().constFirst()->blockSignals(
false);
460 updateAddRemoveButton();
463void SearchRuleWidgetLister::slotAddWidget(QWidget *w)
466 updateAddRemoveButton();
469void SearchRuleWidgetLister::slotRemoveWidget(QWidget *w)
472 updateAddRemoveButton();
481void SearchRuleWidgetLister::updateAddRemoveButton()
483 QList<QWidget *> widgetList =
widgets();
484 const int numberOfWidget(widgetList.
count());
485 bool addButtonEnabled =
false;
486 bool removeButtonEnabled =
false;
488 addButtonEnabled =
true;
489 removeButtonEnabled =
false;
491 addButtonEnabled =
false;
492 removeButtonEnabled =
true;
494 addButtonEnabled =
true;
495 removeButtonEnabled =
true;
499 for (; wIt != wEnd; ++wIt) {
501 w->updateAddRemoveButton(addButtonEnabled, removeButtonEnabled);
505void SearchRuleWidgetLister::reset()
508 regenerateRuleListFromWidgets();
513 updateAddRemoveButton();
516QWidget *SearchRuleWidgetLister::createWidget(QWidget *parent)
523void SearchRuleWidgetLister::clearWidget(QWidget *aWidget)
526 auto w =
static_cast<SearchRuleWidget *
>(aWidget);
529 updateAddRemoveButton();
533void SearchRuleWidgetLister::regenerateRuleListFromWidgets()
544 if (r && !r->isEmpty()) {
545 mRuleList->append(r);
548 updateAddRemoveButton();
557SearchPatternEdit::SearchPatternEdit(QWidget *parent, SearchPatternEditOptions options, SearchModeType modeType)
562 initLayout(options, modeType);
565SearchPatternEdit::~SearchPatternEdit() =
default;
567void SearchPatternEdit::updateSearchPattern()
569 mRuleLister->regenerateRuleListFromWidgets();
572void SearchPatternEdit::setPatternEditOptions(SearchPatternEdit::SearchPatternEditOptions options)
574 mRuleLister->setPatternEditOptions(options);
577void SearchPatternEdit::initLayout(SearchPatternEditOptions options, SearchModeType modeType)
579 auto layout =
new QFormLayout(
this);
580 layout->setContentsMargins({});
582 const bool matchAllMessages = (options & MailCommon::SearchPatternEdit::MatchAllMessages);
584 mAllRBtn =
new QRadioButton(
i18nc(
"@option:radio",
"Match a&ll of the following"),
this);
585 mAnyRBtn =
new QRadioButton(
i18nc(
"@option:radio",
"Match an&y of the following"),
this);
586 if (matchAllMessages) {
587 mAllMessageRBtn =
new QRadioButton(
i18nc(
"@option:radio",
"Match all messages"),
this);
590 mAllRBtn->setObjectName(QLatin1StringView(
"mAllRBtn"));
591 mAllRBtn->setChecked(
true);
592 mAnyRBtn->setObjectName(QLatin1StringView(
"mAnyRBtn"));
593 mAnyRBtn->setChecked(
false);
594 if (matchAllMessages) {
595 mAllMessageRBtn->setObjectName(QLatin1StringView(
"mAllMessageRBtn"));
596 mAllMessageRBtn->setChecked(
false);
598 layout->addRow(
i18n(
"Filter criteria:"), mAllRBtn);
599 layout->addRow(QString(), mAnyRBtn);
600 if (matchAllMessages) {
601 layout->addRow(QString(), mAllMessageRBtn);
604 auto bg =
new QButtonGroup(
this);
605 bg->addButton(mAllRBtn);
606 bg->addButton(mAnyRBtn);
607 if (matchAllMessages) {
608 bg->addButton(mAllMessageRBtn);
615 mRuleLister =
new SearchRuleWidgetLister(
this, options, modeType);
617 mRuleLister->slotClear();
619 if (!mRuleLister->widgets().isEmpty()) {
620 const int numberOfWidget(mRuleLister->widgets().count());
621 for (
int i = 0; i < numberOfWidget; ++i) {
622 SearchRuleWidget *srw =
static_cast<SearchRuleWidget *
>(mRuleLister->widgets().at(i));
625 connect(srw, &SearchRuleWidget::returnPressed,
this, &SearchPatternEdit::returnPressed);
628 qCDebug(MAILCOMMON_LOG) <<
"No first SearchRuleWidget, though slotClear() has been called!";
635 layout->addRow(mRuleLister);
638void SearchPatternEdit::setSearchPattern(
SearchPattern *aPattern)
642 mRuleLister->setRuleList(aPattern);
647 if (mPattern->op() == SearchPattern::OpOr) {
648 mAnyRBtn->setChecked(
true);
649 }
else if (mPattern->op() == SearchPattern::OpAnd) {
650 mAllRBtn->setChecked(
true);
651 }
else if (mAllMessageRBtn && (mPattern->op() == SearchPattern::OpAll)) {
652 mAllMessageRBtn->setChecked(
true);
654 mRuleLister->setEnabled(mPattern->op() != SearchPattern::OpAll);
661void SearchPatternEdit::reset()
663 mRuleLister->reset();
666 mAllRBtn->setChecked(
true);
673void SearchPatternEdit::slotRadioClicked(QAbstractButton *aRBtn)
676 if (aRBtn == mAllRBtn) {
677 mPattern->setOp(SearchPattern::OpAnd);
678 }
else if (aRBtn == mAnyRBtn) {
679 mPattern->setOp(SearchPattern::OpOr);
680 }
else if (aRBtn == mAllMessageRBtn) {
681 mPattern->setOp(SearchPattern::OpAll);
683 mRuleLister->setEnabled(mPattern->op() != SearchPattern::OpAll);
688void SearchPatternEdit::slotAutoNameHack()
690 mRuleLister->regenerateRuleListFromWidgets();
691 Q_EMIT maybeNameChanged();
695void SearchPatternEdit::slotRuleAdded(QWidget *newRuleWidget)
697 auto srw =
static_cast<SearchRuleWidget *
>(newRuleWidget);
700 connect(srw, &SearchRuleWidget::returnPressed,
this, &SearchPatternEdit::returnPressed);
704#include "moc_searchpatternedit.cpp"
KCompletion * completionObject(bool handleSignals=true)
void insertItems(const QStringList &items)
virtual void setCompletionMode(CompletionMode mode)
virtual void setIgnoreCase(bool ignoreCase)
This class is an abstraction of a search over messages.
std::shared_ptr< SearchRule > Ptr
Defines a pointer to a search rule.
Function
Describes operators for comparison of field and contents.
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 i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
void catchReturnKey(QObject *lineEdit)
bool isEmpty() const const
void addItems(const QStringList &texts)
void editTextChanged(const QString &text)
void setMaxCount(int max)
void setItemText(int index, const QString &text)
void textActivated(const QString &text)
QIcon fromTheme(const QString &name)
void append(QList< T > &&value)
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
bool isEmpty() const const
bool blockSignals(bool block)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
T qobject_cast(QObject *object)
void setObjectName(QAnyStringView name)
QString fromLatin1(QByteArrayView str)
QByteArray toLatin1() const const