You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

785 lines
30 KiB

/*
Filter Dialog
Author: Marc Mutz <mutz@kde.org>
based upon work by Stefan Taferner <taferner@kde.org>
Copyright (c) 2011-2015 Laurent Montel <montel@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kmfilterdialog.h"
#include "mailcommon_debug.h"
#include "kmfilterlistbox.h"
#include "filteractions/filteractiondict.h"
#include "filteractions/filteractionwidget.h"
#include "filterimporterexporter.h"
#include "filterselectiondialog.h"
#include "kmfilteraccountlist.h"
using MailCommon::FilterImporterExporter;
#include "filtermanager.h"
#include "folder/folderrequester.h"
#include "kernel/mailkernel.h"
#include "util/mailutil.h"
#include "search/searchpatternedit.h"
#include "filterconverter/filterconverttosieve.h"
#include <ItemFetchJob>
#include <KConfigGroup>
#include <KIconLoader>
#include <KJob>
#include <KKeySequenceWidget>
#include <KListWidgetSearchLine>
#include <KLocalizedString>
#include <KMessageBox>
#include <QPushButton>
#include <QTabWidget>
#include <KWindowSystem>
#include <KIconButton>
#include <KHelpClient>
#include <QIcon>
#include <QApplication>
#include <QHeaderView>
#include <QButtonGroup>
#include <QCheckBox>
#include <QGridLayout>
#include <QLabel>
#include <QListWidget>
#include <QMenu>
#include <QRadioButton>
#include <QTreeWidget>
#include <QVBoxLayout>
#include <QShortcut>
#include <QSplitter>
#include <QPointer>
#include <QKeyEvent>
#include <QHBoxLayout>
#include <QDialogButtonBox>
Q_DECLARE_METATYPE(MailCommon::FilterImporterExporter::FilterType)
using namespace MailCommon;
//=============================================================================
//
// class KMFilterDialog (the filter dialog)
//
//=============================================================================
KMFilterDialog::KMFilterDialog(const QList<KActionCollection *> &actionCollection,
QWidget *parent, bool createDummyFilter)
: QDialog(parent),
mFilter(0),
mDoNotClose(false),
mIgnoreFilterUpdates(true)
{
setWindowTitle(i18n("Filter Rules"));
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Apply);
QVBoxLayout *mainLayout = new QVBoxLayout;
setLayout(mainLayout);
QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
okButton->setDefault(true);
okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
QPushButton *user1Button = new QPushButton;
buttonBox->addButton(user1Button, QDialogButtonBox::ActionRole);
QPushButton *user2Button = new QPushButton;
buttonBox->addButton(user2Button, QDialogButtonBox::ActionRole);
QPushButton *user3Button = new QPushButton;
buttonBox->addButton(user3Button, QDialogButtonBox::ActionRole);
connect(buttonBox, &QDialogButtonBox::accepted, this, &KMFilterDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(buttonBox->button(QDialogButtonBox::Help), &QAbstractButton::clicked, this, &KMFilterDialog::slotHelp);
setModal(false);
okButton->setFocus();
KWindowSystem::setIcons(winId(),
qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),
IconSize(KIconLoader::Desktop)),
qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),
IconSize(KIconLoader::Small)));
user1Button->setText(i18n("Import..."));
user2Button->setText(i18n("Export..."));
user3Button->setText(i18n("Convert to..."));
QMenu *menu = new QMenu();
QAction *act = new QAction(i18n("KMail filters"), this);
act->setData(QVariant::fromValue(MailCommon::FilterImporterExporter::KMailFilter));
menu->addAction(act);
act = new QAction(i18n("Thunderbird filters"), this);
act->setData(QVariant::fromValue(MailCommon::FilterImporterExporter::ThunderBirdFilter));
menu->addAction(act);
act = new QAction(i18n("Evolution filters"), this);
act->setData(QVariant::fromValue(MailCommon::FilterImporterExporter::EvolutionFilter));
menu->addAction(act);
act = new QAction(i18n("Sylpheed filters"), this);
act->setData(QVariant::fromValue(MailCommon::FilterImporterExporter::SylpheedFilter));
menu->addAction(act);
act = new QAction(i18n("Procmail filters"), this);
act->setData(QVariant::fromValue(MailCommon::FilterImporterExporter::ProcmailFilter));
menu->addAction(act);
act = new QAction(i18n("Balsa filters"), this);
act->setData(QVariant::fromValue(MailCommon::FilterImporterExporter::BalsaFilter));
menu->addAction(act);
act = new QAction(i18n("Claws Mail filters"), this);
act->setData(QVariant::fromValue(MailCommon::FilterImporterExporter::ClawsMailFilter));
menu->addAction(act);
act = new QAction(i18n("Icedove Mail filters"), this);
act->setData(QVariant::fromValue(MailCommon::FilterImporterExporter::IcedoveFilter));
menu->addAction(act);
connect(menu, &QMenu::triggered, this, &KMFilterDialog::slotImportFilter);
act = new QAction(i18n("GMail filters"), this);
act->setData(QVariant::fromValue(MailCommon::FilterImporterExporter::GmailFilter));
menu->addAction(act);
user1Button->setMenu(menu);
menu = new QMenu();
act = new QAction(i18n("Sieve script"), this);
connect(act, &QAction::triggered, this, &KMFilterDialog::slotExportAsSieveScript);
menu->addAction(act);
user3Button->setMenu(menu);
connect(user2Button, &QAbstractButton::clicked,
this, &KMFilterDialog::slotExportFilters);
buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
QWidget *w = new QWidget(this);
mainLayout->addWidget(w);
mainLayout->addWidget(buttonBox);
QVBoxLayout *topVLayout = new QVBoxLayout(w);
QHBoxLayout *topLayout = new QHBoxLayout;
topVLayout->addLayout(topLayout);
topLayout->setMargin(0);
QSplitter *splitter = new QSplitter;
splitter->setChildrenCollapsible(false);
topLayout->addWidget(splitter);
mFilterList = new KMFilterListBox(i18n("Available Filters"));
splitter->addWidget(mFilterList);
QTabWidget *tabWidget = new QTabWidget;
splitter->addWidget(tabWidget);
QWidget *page1 = new QWidget(tabWidget);
tabWidget->addTab(page1, i18nc("General mail filter settings.", "General"));
QHBoxLayout *hbl = new QHBoxLayout(page1);
QWidget *page2 = new QWidget(tabWidget);
tabWidget->addTab(page2, i18nc("Advanced mail filter settings.", "Advanced"));
QVBoxLayout *vbl2 = new QVBoxLayout(page2);
QVBoxLayout *vbl = new QVBoxLayout();
hbl->addLayout(vbl);
hbl->setStretchFactor(vbl, 2);
QGroupBox *patternGroupBox = new QGroupBox(i18n("Filter Criteria"), page1);
QHBoxLayout *layout = new QHBoxLayout(patternGroupBox);
mPatternEdit =
new MailCommon::SearchPatternEdit(
patternGroupBox, MailCommon::SearchPatternEdit::MatchAllMessages);
layout->addWidget(mPatternEdit);
vbl->addWidget(patternGroupBox, 0, Qt::AlignTop);
QGroupBox *agb = new QGroupBox(i18n("Filter Actions"), page1);
QHBoxLayout *layout2 = new QHBoxLayout;
mActionLister = new MailCommon::FilterActionWidgetLister(agb);
layout2->addWidget(mActionLister);
agb->setLayout(layout2);
vbl->addWidget(agb, 0, Qt::AlignTop);
mAdvOptsGroup = new QGroupBox(i18n("Advanced Options"), page2);
{
QGridLayout *gl = new QGridLayout();
QVBoxLayout *vbl3 = new QVBoxLayout();
gl->addLayout(vbl3, 0, 0);
vbl3->addStretch(1);
mApplyOnIn = new QCheckBox(i18n("Apply this filter to incoming messages:"), mAdvOptsGroup);
vbl3->addWidget(mApplyOnIn);
QButtonGroup *bg = new QButtonGroup(mAdvOptsGroup);
mApplyOnForAll = new QRadioButton(i18n("from all accounts"), mAdvOptsGroup);
bg->addButton(mApplyOnForAll);
vbl3->addWidget(mApplyOnForAll);
mApplyOnForTraditional =
new QRadioButton(i18n("from all but online IMAP accounts"), mAdvOptsGroup);
bg->addButton(mApplyOnForTraditional);
vbl3->addWidget(mApplyOnForTraditional);
mApplyOnForChecked =
new QRadioButton(i18n("from checked accounts only"), mAdvOptsGroup);
bg->addButton(mApplyOnForChecked);
vbl3->addWidget(mApplyOnForChecked);
vbl3->addStretch(2);
mAccountList = new KMFilterAccountList(mAdvOptsGroup);
gl->addWidget(mAccountList, 0, 1, 4, 3);
mApplyOnOut =
new QCheckBox(i18n("Apply this filter to &sent messages"), mAdvOptsGroup);
mApplyOnOut->setToolTip(
i18n("<p>The filter will be triggered <b>after</b> the message is sent "
"and it will only affect the local copy of the message.</p>"
"<p>If the recipient's copy also needs to be modified, "
"please use \"Apply this filter <b>before</b> sending messages\".</p>"));
gl->addWidget(mApplyOnOut, 4, 0, 1, 4);
mApplyBeforeOut =
new QCheckBox(i18n("Apply this filter &before sending messages"), mAdvOptsGroup);
mApplyBeforeOut->setToolTip(
i18n("<p>The filter will be triggered <b>before</b> the message is sent "
"and it will affect both the local copy and the sent copy of the message.</p>"
"<p>This is required if the recipient's copy also needs to be modified.</p>"));
gl->addWidget(mApplyBeforeOut, 5, 0, 1, 4);
mApplyOnCtrlJ =
new QCheckBox(i18n("Apply this filter on manual &filtering"), mAdvOptsGroup);
gl->addWidget(mApplyOnCtrlJ, 6, 0, 1, 4);
mStopProcessingHere =
new QCheckBox(i18n("If this filter &matches, stop processing here"), mAdvOptsGroup);
gl->addWidget(mStopProcessingHere, 7, 0, 1, 4);
mConfigureShortcut =
new QCheckBox(i18n("Add this filter to the Apply Filter menu"), mAdvOptsGroup);
gl->addWidget(mConfigureShortcut, 8, 0, 1, 2);
QLabel *keyButtonLabel = new QLabel(i18n("Shortcut:"), mAdvOptsGroup);
keyButtonLabel->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
gl->addWidget(keyButtonLabel, 8, 2, 1, 1);
mKeySeqWidget = new KKeySequenceWidget(mAdvOptsGroup);
mKeySeqWidget->setObjectName(QStringLiteral("FilterShortcutSelector"));
gl->addWidget(mKeySeqWidget, 8, 3, 1, 1);
mKeySeqWidget->setEnabled(false);
mKeySeqWidget->setModifierlessAllowed(true);
mKeySeqWidget->setCheckActionCollections(actionCollection);
mConfigureToolbar =
new QCheckBox(i18n("Additionally add this filter to the toolbar"), mAdvOptsGroup);
gl->addWidget(mConfigureToolbar, 9, 0, 1, 4);
mConfigureToolbar->setEnabled(false);
QWidget *hbox = new QWidget(mAdvOptsGroup);
QHBoxLayout *hboxHBoxLayout = new QHBoxLayout(hbox);
hboxHBoxLayout->setMargin(0);
mFilterActionLabel = new QLabel(i18n("Icon for this filter:"), hbox);
hboxHBoxLayout->addWidget(mFilterActionLabel);
mFilterActionLabel->setEnabled(false);
mFilterActionIconButton = new KIconButton(hbox);
hboxHBoxLayout->addWidget(mFilterActionIconButton);
mFilterActionLabel->setBuddy(mFilterActionIconButton);
mFilterActionIconButton->setIconType(KIconLoader::NoGroup, KIconLoader::Action, false);
mFilterActionIconButton->setIconSize(16);
mFilterActionIconButton->setIcon(QIcon::fromTheme(QStringLiteral("system-run")));
mFilterActionIconButton->setEnabled(false);
gl->addWidget(hbox, 10, 0, 1, 4);
mAdvOptsGroup->setLayout(gl);
}
vbl2->addWidget(mAdvOptsGroup, 0, Qt::AlignTop);
QHBoxLayout *applySpecificFiltersLayout = new QHBoxLayout;
QLabel *lab = new QLabel(i18n("Run selected filter(s) on: "));
applySpecificFiltersLayout->addWidget(lab);
mFolderRequester = new MailCommon::FolderRequester;
mFolderRequester->setNotAllowToCreateNewFolder(true);
applySpecificFiltersLayout->addWidget(mFolderRequester);
connect(mFolderRequester, &FolderRequester::folderChanged,
this, &KMFilterDialog::slotFolderChanged);
mRunNow = new QPushButton(i18n("Run Now"));
mRunNow->setEnabled(false);
applySpecificFiltersLayout->addWidget(mRunNow);
connect(mRunNow, &QPushButton::clicked, this, &KMFilterDialog::slotRunFilters);
topVLayout->addLayout(applySpecificFiltersLayout);
// spacer:
vbl->addStretch(1);
// load the filter parts into the edit widgets
connect(mFilterList, &KMFilterListBox::filterSelected, this, &KMFilterDialog::slotFilterSelected);
// transfer changes from the 'Apply this filter on...'
// combo box to the filter
connect(mApplyOnIn, &QCheckBox::clicked, this, &KMFilterDialog::slotApplicabilityChanged);
connect(mApplyOnForAll, &QRadioButton::clicked, this, &KMFilterDialog::slotApplicabilityChanged);
connect(mApplyOnForTraditional, &QAbstractButton::clicked, this, &KMFilterDialog::slotApplicabilityChanged);
connect(mApplyOnForChecked, &QAbstractButton::clicked, this, &KMFilterDialog::slotApplicabilityChanged);
connect(mApplyBeforeOut, &QAbstractButton::clicked, this, &KMFilterDialog::slotApplicabilityChanged);
connect(mApplyOnOut, &QAbstractButton::clicked, this, &KMFilterDialog::slotApplicabilityChanged);
connect(mApplyOnCtrlJ, &QAbstractButton::clicked, this, &KMFilterDialog::slotApplicabilityChanged);
connect(mAccountList, &KMFilterAccountList::itemChanged, this, &KMFilterDialog::slotApplicableAccountsChanged);
// transfer changes from the 'stop processing here'
// check box to the filter
connect(mStopProcessingHere, &QCheckBox::toggled, this, &KMFilterDialog::slotStopProcessingButtonToggled);
connect(mConfigureShortcut, &QCheckBox::toggled, this, &KMFilterDialog::slotConfigureShortcutButtonToggled);
connect(mKeySeqWidget, &KKeySequenceWidget::keySequenceChanged, this, &KMFilterDialog::slotShortcutChanged);
connect(mConfigureToolbar, &QCheckBox::toggled, this, &KMFilterDialog::slotConfigureToolbarButtonToggled);
connect(mFilterActionIconButton, &KIconButton::iconChanged, this, &KMFilterDialog::slotFilterActionIconChanged);
// reset all widgets here
connect(mFilterList, &KMFilterListBox::resetWidgets, this, &KMFilterDialog::slotReset);
connect(mFilterList, &KMFilterListBox::applyWidgets, this, &KMFilterDialog::slotUpdateFilter);
// support auto-naming the filter
connect(mPatternEdit, &MailCommon::SearchPatternEdit::maybeNameChanged, mFilterList, &KMFilterListBox::slotUpdateFilterName);
// save filters on 'Apply' or 'OK'
connect(buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked,
this, &KMFilterDialog::slotApply);
// save dialog size on 'OK'
connect(okButton, &QAbstractButton::clicked,
this, &KMFilterDialog::slotSaveSize);
// destruct the dialog on close and Cancel
connect(buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked,
this, &KMFilterDialog::slotFinished);
// disable closing when user wants to continue editing
connect(mFilterList, &KMFilterListBox::abortClosing,
this, &KMFilterDialog::slotDisableAccept);
connect(mFilterList, &KMFilterListBox::filterCreated, this, &KMFilterDialog::slotDialogUpdated);
connect(mFilterList, &KMFilterListBox::filterRemoved,
this, &KMFilterDialog::slotDialogUpdated);
connect(mFilterList, &KMFilterListBox::filterUpdated,
this, &KMFilterDialog::slotDialogUpdated);
connect(mFilterList, &KMFilterListBox::filterOrderAltered, this, &KMFilterDialog::slotDialogUpdated);
connect(mPatternEdit, &MailCommon::SearchPatternEdit::patternChanged, this, &KMFilterDialog::slotDialogUpdated);
connect(mActionLister, SIGNAL(widgetAdded(QWidget*)), this, SLOT(slotDialogUpdated()));
connect(mActionLister, SIGNAL(widgetRemoved()), this, SLOT(slotDialogUpdated()));
connect(mActionLister, &MailCommon::FilterActionWidgetLister::filterModified, this, &KMFilterDialog::slotDialogUpdated);
connect(mActionLister, &MailCommon::FilterActionWidgetLister::clearWidgets, this, &KMFilterDialog::slotDialogUpdated);
KConfigGroup myGroup(KernelIf->config(), "Geometry");
const QSize size = myGroup.readEntry("filterDialogSize", QSize());
if (size != QSize()) {
resize(size);
} else {
adjustSize();
}
// load the filter list (emits filterSelected())
mFilterList->loadFilterList(createDummyFilter);
mIgnoreFilterUpdates = false;
}
void KMFilterDialog::createFilter(const QByteArray &field, const QString &value)
{
mFilterList->createFilter(field, value);
}
void KMFilterDialog::accept()
{
if (mDoNotClose) {
mDoNotClose = false; // only abort current close attempt
} else {
QDialog::accept();
slotFinished();
}
}
bool KMFilterDialog::event(QEvent *e)
{
// Close the bar when pressing Escape.
// Not using a QShortcut for this because it could conflict with
// window-global actions (e.g. Emil Sedgh binds Esc to "close tab").
// With a shortcut override we can catch this before it gets to kactions.
const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride);
if (shortCutOverride || e->type() == QEvent::KeyPress) {
QKeyEvent *kev = static_cast<QKeyEvent * >(e);
if (kev->key() == Qt::Key_Escape) {
e->ignore();
return true;
}
}
return QDialog::event(e);
}
void KMFilterDialog::slotApply()
{
buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
mFilterList->slotApplied();
}
void KMFilterDialog::slotFinished()
{
deleteLater();
}
void KMFilterDialog::slotFolderChanged(const Akonadi::Collection &collection)
{
mRunNow->setEnabled(collection.isValid());
}
void KMFilterDialog::slotRunFilters()
{
if (!mFolderRequester->collection().isValid()) {
KMessageBox::information(
this,
i18nc("@info",
"Unable to apply this filter since there are no folders selected."),
i18n("No folder selected."));
return;
}
if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
KMessageBox::information(
this,
i18nc("@info",
"Some filters were changed and not saved yet. "
"You must save your filters before they can be applied."),
i18n("Filters changed."));
return;
}
SearchRule::RequiredPart requiredPart = SearchRule::Envelope;
const QStringList selectedFiltersId = mFilterList->selectedFilterId(requiredPart, mFolderRequester->collection().resource());
if (selectedFiltersId.isEmpty()) {
KMessageBox::information(
this,
i18nc("@info",
"Unable to apply a filter since there are no filters currently selected."),
i18n("No filters selected."));
return;
}
Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob(mFolderRequester->collection(), this);
job->setProperty("requiredPart", QVariant::fromValue(requiredPart));
job->setProperty("listFilters", QVariant::fromValue(selectedFiltersId));
connect(job, &KJob::result,
this, &KMFilterDialog::slotFetchItemsForFolderDone);
mRunNow->setEnabled(false); //Disable it
}
void KMFilterDialog::slotFetchItemsForFolderDone(KJob *job)
{
Akonadi::ItemFetchJob *fjob = dynamic_cast<Akonadi::ItemFetchJob *>(job);
Q_ASSERT(fjob);
QStringList filtersId;
if (fjob->property("listFilters").isValid()) {
filtersId = fjob->property("listFilters").toStringList();
}
SearchRule::RequiredPart requiredPart = SearchRule::Envelope;
if (fjob->property("requiredPart").isValid()) {
requiredPart = fjob->property("requiredPart").value<SearchRule::RequiredPart>();
}
Akonadi::Item::List items = fjob->items();
mRunNow->setEnabled(true);
MailCommon::FilterManager::instance()->filter(items, requiredPart, filtersId);
}
void KMFilterDialog::slotSaveSize()
{
mFilterList->slotAccepted();
KConfigGroup myGroup(KernelIf->config(), "Geometry");
myGroup.writeEntry("filterDialogSize", size());
myGroup.sync();
}
void KMFilterDialog::slotFilterSelected(MailFilter *aFilter)
{
Q_ASSERT(aFilter);
mIgnoreFilterUpdates = true;
mActionLister->setActionList(aFilter->actions());
mAdvOptsGroup->setEnabled(true);
mPatternEdit->setSearchPattern(aFilter->pattern());
mFilter = aFilter;
qCDebug(MAILCOMMON_LOG) << "apply on inbound ==" << aFilter->applyOnInbound();
qCDebug(MAILCOMMON_LOG) << "apply on outbound ==" << aFilter->applyOnOutbound();
qCDebug(MAILCOMMON_LOG) << "apply before outbound == " << aFilter->applyBeforeOutbound();
qCDebug(MAILCOMMON_LOG) << "apply on explicit ==" << aFilter->applyOnExplicit();
// NOTE: setting these values activates the slot that sets them in
// the filter! So make sure we have the correct values _before_ we
// set the first one:
const bool applyOnIn = aFilter->applyOnInbound();
const bool applyOnForAll = aFilter->applicability() == MailFilter::All;
const bool applyOnTraditional = aFilter->applicability() == MailFilter::ButImap;
const bool applyBeforeOut = aFilter->applyBeforeOutbound();
const bool applyOnOut = aFilter->applyOnOutbound();
const bool applyOnExplicit = aFilter->applyOnExplicit();
const bool stopHere = aFilter->stopProcessingHere();
const bool configureShortcut = aFilter->configureShortcut();
const bool configureToolbar = aFilter->configureToolbar();
const QString icon = aFilter->icon();
const QKeySequence shortcut(aFilter->shortcut());
mApplyOnIn->setChecked(applyOnIn);
mApplyOnForAll->setEnabled(applyOnIn);
mApplyOnForTraditional->setEnabled(applyOnIn);
mApplyOnForChecked->setEnabled(applyOnIn);
mApplyOnForAll->setChecked(applyOnForAll);
mApplyOnForTraditional->setChecked(applyOnTraditional);
mApplyOnForChecked->setChecked(!applyOnForAll && !applyOnTraditional);
mAccountList->setEnabled(mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked());
slotUpdateAccountList();
mApplyBeforeOut->setChecked(applyBeforeOut);
mApplyOnOut->setChecked(applyOnOut);
mApplyOnCtrlJ->setChecked(applyOnExplicit);
mStopProcessingHere->setChecked(stopHere);
mConfigureShortcut->setChecked(configureShortcut);
mKeySeqWidget->setKeySequence(shortcut,
KKeySequenceWidget::NoValidate);
mConfigureToolbar->setChecked(configureToolbar);
mFilterActionIconButton->setIcon(icon);
mIgnoreFilterUpdates = false;
}
void KMFilterDialog::slotReset()
{
mFilter = 0;
mPatternEdit->reset();
mActionLister->reset();
mAdvOptsGroup->setEnabled(false);
slotUpdateAccountList();
}
void KMFilterDialog::slotUpdateFilter()
{
mPatternEdit->updateSearchPattern();
mActionLister->updateActionList();
}
void KMFilterDialog::slotApplicabilityChanged()
{
if (mFilter) {
mFilter->setApplyOnInbound(mApplyOnIn->isChecked());
mFilter->setApplyBeforeOutbound(mApplyBeforeOut->isChecked());
mFilter->setApplyOnOutbound(mApplyOnOut->isChecked());
mFilter->setApplyOnExplicit(mApplyOnCtrlJ->isChecked());
if (mApplyOnForAll->isChecked()) {
mFilter->setApplicability(MailFilter::All);
mFilter->clearApplyOnAccount();
} else if (mApplyOnForTraditional->isChecked()) {
mFilter->setApplicability(MailFilter::ButImap);
} else if (mApplyOnForChecked->isChecked()) {
mFilter->setApplicability(MailFilter::Checked);
}
mApplyOnForAll->setEnabled(mApplyOnIn->isChecked());
mApplyOnForTraditional->setEnabled(mApplyOnIn->isChecked());
mApplyOnForChecked->setEnabled(mApplyOnIn->isChecked());
mAccountList->setEnabled(mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked());
// Advanced tab functionality - Update list of accounts this filter applies to
if (!mApplyOnForAll->isChecked()) {
mAccountList->applyOnAccount(mFilter);
}
// Enable the apply button
slotDialogUpdated();
qCDebug(MAILCOMMON_LOG) << "Setting filter to be applied at"
<< (mFilter->applyOnInbound() ? "incoming " : "")
<< (mFilter->applyOnOutbound() ? "outgoing " : "")
<< (mFilter->applyBeforeOutbound() ? "before_outgoing " : "")
<< (mFilter->applyOnExplicit() ? "explicit CTRL-J" : "");
}
}
void KMFilterDialog::slotApplicableAccountsChanged()
{
// Advanced tab functionality - Update list of accounts this filter applies to
if (mFilter && mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked()) {
QTreeWidgetItemIterator it(mAccountList);
while (QTreeWidgetItem *item = *it) {
const QString id = item->text(2);
mFilter->setApplyOnAccount(id, item->checkState(0) == Qt::Checked);
++it;
}
// Enable the apply button
slotDialogUpdated();
}
}
void KMFilterDialog::slotStopProcessingButtonToggled(bool aChecked)
{
if (mFilter) {
mFilter->setStopProcessingHere(aChecked);
// Enable the apply button
slotDialogUpdated();
}
}
void KMFilterDialog::slotConfigureShortcutButtonToggled(bool aChecked)
{
if (mFilter) {
mFilter->setConfigureShortcut(aChecked);
mKeySeqWidget->setEnabled(aChecked);
mConfigureToolbar->setEnabled(aChecked);
mFilterActionIconButton->setEnabled(aChecked);
mFilterActionLabel->setEnabled(aChecked);
// Enable the apply button
slotDialogUpdated();
}
}
void KMFilterDialog::slotShortcutChanged(const QKeySequence &newSeq)
{
if (mFilter) {
mKeySeqWidget->applyStealShortcut();
mFilter->setShortcut(newSeq);
// Enable the apply button
slotDialogUpdated();
}
}
void KMFilterDialog::slotConfigureToolbarButtonToggled(bool aChecked)
{
if (mFilter) {
mFilter->setConfigureToolbar(aChecked);
// Enable the apply button
slotDialogUpdated();
}
}
void KMFilterDialog::slotFilterActionIconChanged(const QString &icon)
{
if (mFilter) {
mFilter->setIcon(icon);
// Enable the apply button
slotDialogUpdated();
}
}
void KMFilterDialog::slotUpdateAccountList()
{
mAccountList->updateAccountList(mFilter);
}
void KMFilterDialog::slotImportFilter(QAction *act)
{
if (act) {
importFilters(act->data().value<MailCommon::FilterImporterExporter::FilterType>());
}
}
void KMFilterDialog::importFilters(MailCommon::FilterImporterExporter::FilterType type)
{
FilterImporterExporter importer(this);
bool canceled = false;
QList<MailFilter *> filters = importer.importFilters(canceled, type);
if (canceled) {
return;
}
if (filters.isEmpty()) {
KMessageBox::information(this, i18n("No filter was imported."));
return;
}
QStringList listOfFilter;
QList<MailFilter *>::ConstIterator end(filters.constEnd());
for (QList<MailFilter *>::ConstIterator it = filters.constBegin(); it != end; ++it) {
mFilterList->appendFilter(*it); // no need to deep copy, ownership passes to the list
listOfFilter << (*it)->name();
}
KMessageBox::informationList(
this,
i18n("Filters which were imported:"),
listOfFilter);
}
void KMFilterDialog::slotExportFilters()
{
FilterImporterExporter exporter(this);
bool wasCanceled = false;
const QList<MailFilter *> filters = mFilterList->filtersForSaving(false, wasCanceled);
exporter.exportFilters(filters);
}
void KMFilterDialog::slotDisableAccept()
{
mDoNotClose = true;
}
void KMFilterDialog::slotDialogUpdated()
{
qCDebug(MAILCOMMON_LOG) << "Detected a change in data bound to the dialog!";
if (!mIgnoreFilterUpdates) {
buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true);
}
}
void KMFilterDialog::slotExportAsSieveScript()
{
if (buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) {
KMessageBox::information(
this,
i18nc("@info",
"Some filters were changed and not saved yet.<br>"
"You must save your filters before they can be exported."),
i18n("Filters changed."));
return;
}
KMessageBox::information(this, i18n("We cannot convert all KMail filters to sieve scripts but we can try :)"), i18n("Convert KMail filters to sieve scripts"));
bool wasCanceled = false;
const QList<MailFilter *> filters = mFilterList->filtersForSaving(false, wasCanceled);
QPointer<FilterSelectionDialog> dlg = new FilterSelectionDialog(this);
dlg->setFilters(filters);
if (dlg->exec() == QDialog::Accepted) {
QList<MailFilter *> lst = dlg->selectedFilters();
if (!lst.isEmpty()) {
FilterConvertToSieve convert(lst);
convert.convert();
qDeleteAll(lst);
} else {
KMessageBox::information(this, i18n("No filters selected."), i18n("Convert KMail filters to sieve scripts"));
}
}
delete dlg;
}
void KMFilterDialog::slotHelp()
{
KHelpClient::invokeHelp(QStringLiteral("filters"), QStringLiteral("kmail"));
}