filtereditdialog.cpp 12.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
  This file is part of KOrganizer.

  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
  Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
  Copyright (C) 2005 Thomas Zander <zander@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.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "filtereditdialog.h"
28
29
#include "korganizer_debug.h"

30
#include <KCalendarCore/CalFilter>
31

32
#include <Libkdepim/LineEditCatchReturnKey>
33

34
35
#include <AkonadiWidgets/TagSelectionDialog>

36
#include <PimCommon/PimUtil>
37
38

#include <KMessageBox>
39
40
#include <KColorScheme>

Laurent Montel's avatar
Laurent Montel committed
41
#include <QDialogButtonBox>
42

43
FilterEditDialog::FilterEditDialog(QList<KCalendarCore::CalFilter *> *filters, QWidget *parent)
Laurent Montel's avatar
Laurent Montel committed
44
    : QDialog(parent)
45
{
Laurent Montel's avatar
Laurent Montel committed
46
    setWindowTitle(i18nc("@title::window", "Edit Calendar Filters"));
Laurent Montel's avatar
Laurent Montel committed
47
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
Laurent Montel's avatar
Laurent Montel committed
48

Laurent Montel's avatar
Laurent Montel committed
49
50
    QDialogButtonBox *buttonBox = new QDialogButtonBox(
        QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply, this);
Laurent Montel's avatar
Laurent Montel committed
51
52
53
54
55
56
57
58
59
60
61
62
63
    mOkButton = buttonBox->button(QDialogButtonBox::Ok);
    mApplyButton = buttonBox->button(QDialogButtonBox::Apply);
    mOkButton->setDefault(true);
    mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return);
    connect(buttonBox, &QDialogButtonBox::accepted, this, &FilterEditDialog::slotOk);
    connect(buttonBox, &QDialogButtonBox::rejected, this, &FilterEditDialog::reject);
    mainLayout->addWidget(mFilterEdit = new FilterEdit(filters, this));
    mainLayout->addWidget(buttonBox);

    connect(mFilterEdit, &FilterEdit::dataConsistent, this, &FilterEditDialog::setDialogConsistent);
    updateFilterList();
    connect(mFilterEdit, &FilterEdit::editCategories, this, &FilterEditDialog::editCategories);
    connect(mFilterEdit, &FilterEdit::filterChanged, this, &FilterEditDialog::filterChanged);
Laurent Montel's avatar
Laurent Montel committed
64
65
66
    connect(buttonBox->button(
                QDialogButtonBox::Apply), &QPushButton::clicked, this,
            &FilterEditDialog::slotApply);
67
68
69
70
}

FilterEditDialog::~FilterEditDialog()
{
Laurent Montel's avatar
Laurent Montel committed
71
    delete mFilterEdit;
Laurent Montel's avatar
Laurent Montel committed
72
    mFilterEdit = nullptr;
73
74
75
76
}

void FilterEditDialog::updateFilterList()
{
Laurent Montel's avatar
Laurent Montel committed
77
    mFilterEdit->updateFilterList();
78
79
80
81
}

void FilterEditDialog::slotApply()
{
Laurent Montel's avatar
Laurent Montel committed
82
    mFilterEdit->saveChanges();
83
84
85
86
}

void FilterEditDialog::slotOk()
{
Laurent Montel's avatar
Laurent Montel committed
87
88
    slotApply();
    accept();
89
90
}

Laurent Montel's avatar
Laurent Montel committed
91
void FilterEditDialog::setDialogConsistent(bool consistent)
92
{
Laurent Montel's avatar
Laurent Montel committed
93
    mOkButton->setEnabled(consistent);
Laurent Montel's avatar
Laurent Montel committed
94
    mApplyButton->setEnabled(consistent);
95
96
}

97
FilterEdit::FilterEdit(QList<KCalendarCore::CalFilter *> *filters, QWidget *parent)
Laurent Montel's avatar
Laurent Montel committed
98
    : QWidget(parent)
99
{
Laurent Montel's avatar
Laurent Montel committed
100
101
    setupUi(this);
    searchline->setListWidget(mRulesList);
102
    new KPIM::LineEditCatchReturnKey(mNameLineEdit, this);
Laurent Montel's avatar
Laurent Montel committed
103
104
105
106
107
108
109
110
111
    mDetailsFrame->setEnabled(false);
    mFilters = filters;
    mNewButton->setWhatsThis(
        i18nc("@info:whatsthis",
              "Press this button to define a new filter."));
    mDeleteButton->setWhatsThis(
        i18nc("@info:whatsthis",
              "Press this button to remove the currently active filter."));

112
113
    connect(mRulesList, qOverload<>(&QListWidget::itemSelectionChanged),
            this, qOverload<>(&FilterEdit::filterSelected));
Laurent Montel's avatar
Laurent Montel committed
114
115
116
117
118
119
120

    connect(mNewButton, &QPushButton::clicked, this, &FilterEdit::bNewPressed);
    connect(mDeleteButton, &QPushButton::clicked, this, &FilterEdit::bDeletePressed);
    connect(mNameLineEdit, &QLineEdit::textChanged, this, &FilterEdit::updateSelectedName);
    connect(mCatEditButton, &QPushButton::clicked, this, &FilterEdit::editCategorySelection);
    connect(mCompletedCheck, &QCheckBox::toggled, mCompletedTimeSpanLabel, &QLabel::setEnabled);
    connect(mCompletedCheck, &QCheckBox::toggled, mCompletedTimeSpan, &QSpinBox::setEnabled);
121
122
123
124
125
126
127
128
}

FilterEdit::~FilterEdit()
{
}

void FilterEdit::updateFilterList()
{
Laurent Montel's avatar
Laurent Montel committed
129
130
131
    mRulesList->clear();
    if (!mFilters || mFilters->empty()) {
        mDetailsFrame->setEnabled(false);
132
        Q_EMIT dataConsistent(false);
Laurent Montel's avatar
Laurent Montel committed
133
    } else {
134
135
        QList<KCalendarCore::CalFilter *>::iterator i;
        QList<KCalendarCore::CalFilter *>::iterator end(mFilters->end());
Laurent Montel's avatar
Laurent Montel committed
136
        for (i = mFilters->begin(); i != end; ++i) {
Laurent Montel's avatar
Laurent Montel committed
137
138
139
140
141
            if (*i) {
                mRulesList->addItem((*i)->name());
            }
        }
        if (mRulesList->currentRow() != -1) {
142
            KCalendarCore::CalFilter *f = mFilters->at(mRulesList->currentRow());
Laurent Montel's avatar
Laurent Montel committed
143
144
145
146
            if (f) {
                filterSelected(f);
            }
        }
147
        Q_EMIT dataConsistent(true);
Laurent Montel's avatar
Laurent Montel committed
148
    }
Laurent Montel's avatar
Laurent Montel committed
149
    if (mFilters && !mFilters->isEmpty() && !mCurrent) {
Laurent Montel's avatar
Laurent Montel committed
150
151
152
153
        filterSelected(mFilters->at(0));
    }
    if (mFilters) {
        mDeleteButton->setEnabled(!mFilters->isEmpty());
154
155
156
157
158
    }
}

void FilterEdit::saveChanges()
{
Laurent Montel's avatar
Laurent Montel committed
159
160
161
162
163
164
165
    if (!mCurrent) {
        return;
    }

    mCurrent->setName(mNameLineEdit->text());
    int criteria = 0;
    if (mCompletedCheck->isChecked()) {
166
        criteria |= KCalendarCore::CalFilter::HideCompletedTodos;
167
    }
Laurent Montel's avatar
Laurent Montel committed
168
    if (mRecurringCheck->isChecked()) {
169
        criteria |= KCalendarCore::CalFilter::HideRecurring;
Laurent Montel's avatar
Laurent Montel committed
170
171
    }
    if (mCatShowCheck->isChecked()) {
172
        criteria |= KCalendarCore::CalFilter::ShowCategories;
Laurent Montel's avatar
Laurent Montel committed
173
174
    }
    if (mHideInactiveTodosCheck->isChecked()) {
175
        criteria |= KCalendarCore::CalFilter::HideInactiveTodos;
Laurent Montel's avatar
Laurent Montel committed
176
177
    }
    if (mHideTodosNotAssignedToMeCheck->isChecked()) {
178
        criteria |= KCalendarCore::CalFilter::HideNoMatchingAttendeeTodos;
Laurent Montel's avatar
Laurent Montel committed
179
180
181
182
183
    }
    mCurrent->setCriteria(criteria);
    mCurrent->setCompletedTimeSpan(mCompletedTimeSpan->value());

    QStringList categoryList;
Laurent Montel's avatar
Minor    
Laurent Montel committed
184
185
    const int numberOfCat(mCatList->count());
    for (int i = 0; i < numberOfCat; ++i) {
Laurent Montel's avatar
Laurent Montel committed
186
187
188
189
190
191
        QListWidgetItem *item = mCatList->item(i);
        if (item) {
            categoryList.append(item->text());
        }
    }
    mCurrent->setCategoryList(categoryList);
Laurent Montel's avatar
Laurent Montel committed
192
    Q_EMIT filterChanged();
193
194
195
196
}

void FilterEdit::filterSelected()
{
Laurent Montel's avatar
Laurent Montel committed
197
198
199
200
    if (mRulesList->currentRow() < mFilters->count()) {
        mDetailsFrame->setEnabled(true);
        filterSelected(mFilters->at(mRulesList->currentRow()));
    }
201
202
}

203
void FilterEdit::filterSelected(KCalendarCore::CalFilter *filter)
204
{
Laurent Montel's avatar
Laurent Montel committed
205
206
207
    if (!filter || filter == mCurrent) {
        return;
    }
Laurent Montel's avatar
Laurent Montel committed
208
    qCDebug(KORGANIZER_LOG) << "Selected filter" << filter->name();
Laurent Montel's avatar
Laurent Montel committed
209
210
211
212
213
214
215
    saveChanges();

    mCurrent = filter;
    mNameLineEdit->blockSignals(true);
    mNameLineEdit->setText(mCurrent->name());
    mNameLineEdit->blockSignals(false);
    mDetailsFrame->setEnabled(true);
216
    mCompletedCheck->setChecked(mCurrent->criteria() & KCalendarCore::CalFilter::HideCompletedTodos);
Laurent Montel's avatar
Laurent Montel committed
217
    mCompletedTimeSpan->setValue(mCurrent->completedTimeSpan());
218
    mRecurringCheck->setChecked(mCurrent->criteria() & KCalendarCore::CalFilter::HideRecurring);
Laurent Montel's avatar
Laurent Montel committed
219
    mHideInactiveTodosCheck->setChecked(
220
        mCurrent->criteria() & KCalendarCore::CalFilter::HideInactiveTodos);
Laurent Montel's avatar
Laurent Montel committed
221
    mHideTodosNotAssignedToMeCheck->setChecked(
222
        mCurrent->criteria() & KCalendarCore::CalFilter::HideNoMatchingAttendeeTodos);
Laurent Montel's avatar
Laurent Montel committed
223

224
    if (mCurrent->criteria() & KCalendarCore::CalFilter::ShowCategories) {
Laurent Montel's avatar
Laurent Montel committed
225
226
227
228
229
230
        mCatShowCheck->setChecked(true);
    } else {
        mCatHideCheck->setChecked(true);
    }
    mCatList->clear();
    mCatList->addItems(mCurrent->categoryList());
231
232
233
234
}

void FilterEdit::bNewPressed()
{
Laurent Montel's avatar
Laurent Montel committed
235
236
    mDetailsFrame->setEnabled(true);
    saveChanges();
Laurent Montel's avatar
Laurent Montel committed
237
    QStringList filterNames;
238
239
240
    const int numRules = mRulesList->count();
    filterNames.reserve(numRules);
    for (int i = 0; i < numRules; ++i) {
Laurent Montel's avatar
Laurent Montel committed
241
242
243
244
245
246
247
248
249
250
        filterNames << mRulesList->item(i)->text();
    }
    QString newFilterName;
    for (int i = 1;; ++i) {
        newFilterName = i18nc("@label default filter name",
                              "New Filter %1", i);
        if (!filterNames.contains(newFilterName)) {
            break;
        }
    }
251

252
253
    KCalendarCore::CalFilter *newFilter
        = new KCalendarCore::CalFilter(newFilterName);
Laurent Montel's avatar
Laurent Montel committed
254
255
256
    mFilters->append(newFilter);
    updateFilterList();
    mRulesList->setCurrentRow(mRulesList->count() - 1);
Laurent Montel's avatar
Laurent Montel committed
257
    Q_EMIT filterChanged();
258
259
260
261
}

void FilterEdit::bDeletePressed()
{
Laurent Montel's avatar
Laurent Montel committed
262
263
264
265
266
267
268
269
    if (!mRulesList->currentItem()) {   // nothing selected
        return;
    }
    if (mFilters->isEmpty()) {   // We need at least a default filter object.
        return;
    }

    if (KMessageBox::warningContinueCancel(
Laurent Montel's avatar
Laurent Montel committed
270
271
272
273
274
            this,
            i18nc("@info",
                  "Do you really want to permanently remove the filter \"%1\"?", mCurrent->name()),
            i18nc("@title:window", "Delete Filter?"),
            KStandardGuiItem::del()) == KMessageBox::Cancel) {
Laurent Montel's avatar
Laurent Montel committed
275
276
277
278
        return;
    }

    int selected = mRulesList->currentRow();
279
    KCalendarCore::CalFilter *filter = mFilters->at(selected);
Laurent Montel's avatar
Laurent Montel committed
280
281
    mFilters->removeAll(filter);
    delete filter;
Laurent Montel's avatar
Laurent Montel committed
282
    mCurrent = nullptr;
Laurent Montel's avatar
Laurent Montel committed
283
284
    updateFilterList();
    mRulesList->setCurrentRow(qMin(mRulesList->count() - 1, selected));
Laurent Montel's avatar
Laurent Montel committed
285
    Q_EMIT filterChanged();
286
287
}

Laurent Montel's avatar
Laurent Montel committed
288
void FilterEdit::updateSelectedName(const QString &newText)
289
{
Laurent Montel's avatar
Laurent Montel committed
290
291
292
293
    mRulesList->blockSignals(true);
    QListWidgetItem *item = mRulesList->currentItem();
    if (item) {
        item->setText(newText);
294
    }
Laurent Montel's avatar
Laurent Montel committed
295
296
    mRulesList->blockSignals(false);
    if (correctName(newText)) {
Laurent Montel's avatar
Laurent Montel committed
297
        Q_EMIT dataConsistent(false);
Laurent Montel's avatar
Laurent Montel committed
298
299
300
        return;
    }
    bool allOk = true;
301

302
    for (KCalendarCore::CalFilter *i : qAsConst(*mFilters)) {
Laurent Montel's avatar
Laurent Montel committed
303
304
305
306
307
        if (i && i->name().isEmpty()) {
            allOk = false;
        }
    }

Laurent Montel's avatar
Laurent Montel committed
308
    Q_EMIT dataConsistent(allOk);
309
310
}

311
312
bool FilterEdit::correctName(const QString &newText)
{
Laurent Montel's avatar
Laurent Montel committed
313
    bool negative = false;
314
315
316
#ifndef QT_NO_STYLE_STYLESHEET
    QString styleSheet;
    if (mNegativeBackground.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
317
318
319
320
321
        const KStatefulBrush bgBrush = KStatefulBrush(KColorScheme::View,
                                                      KColorScheme::NegativeBackground);
        mNegativeBackground
            = QStringLiteral("QLineEdit{ background-color:%1 }").arg(bgBrush.brush(
                                                                         mNameLineEdit).color().name());
322
323
    }
    if (!newText.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
324
325
        const int val = mRulesList->count();
        for (int i = 0; i < val; ++i) {
326
            QListWidgetItem *item = mRulesList->item(i);
Laurent Montel's avatar
Laurent Montel committed
327
            if (item && (mRulesList->currentItem() != item)) {
328
329
330
331
332
333
334
335
336
                if (newText == item->text()) {
                    negative = true;
                    break;
                }
            }
        }
    } else {
        negative = true;
    }
Laurent Montel's avatar
Laurent Montel committed
337
    if (negative) {
338
        styleSheet = mNegativeBackground;
Laurent Montel's avatar
Laurent Montel committed
339
    }
340
341
342
343
344
    mNameLineEdit->setStyleSheet(styleSheet);
#endif
    return negative;
}

345
346
void FilterEdit::editCategorySelection()
{
Laurent Montel's avatar
Laurent Montel committed
347
348
349
350
351
    if (!mCurrent) {
        return;
    }

    if (!mCategorySelectDialog) {
352
        mCategorySelectDialog = new Akonadi::TagSelectionDialog(this);
353
354
355
356
        QDialogButtonBox *buttons = mCategorySelectDialog->buttons();
        if (buttons) {
            buttons->setStandardButtons(
                QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help);
357
            connect(mCategorySelectDialog, &Akonadi::TagSelectionDialog::accepted,
358
359
360
361
                    this, &FilterEdit::updateCategorySelection);
            connect(buttons->button(QDialogButtonBox::Help), &QPushButton::clicked,
                    this, &FilterEdit::slotHelp);
        }
Laurent Montel's avatar
Laurent Montel committed
362
    }
363
364
365
366
367
368
    Akonadi::Tag::List tags;
    const auto names = mCurrent->categoryList();
    tags.resize(names.size());
    std::transform(names.cbegin(), names.cend(), std::back_inserter(tags),
                   [](const QString &name) { return Akonadi::Tag{name}; });
    mCategorySelectDialog->setSelection(tags);
Laurent Montel's avatar
Laurent Montel committed
369
370

    mCategorySelectDialog->show();
371
372
}

373
374
void FilterEdit::slotHelp()
{
Laurent Montel's avatar
Laurent Montel committed
375
    PimCommon::Util::invokeHelp(QStringLiteral("korganizer/filters-view.html"));
376
377
}

378
void FilterEdit::updateCategorySelection()
379
{
380
381
382
383
384
    const auto tags = mCategorySelectDialog->selection();
    QStringList categories;
    categories.reserve(tags.size());
    std::transform(tags.cbegin(), tags.cend(), std::back_inserter(categories),
                   std::bind(&Akonadi::Tag::name, std::placeholders::_1));
Laurent Montel's avatar
Laurent Montel committed
385
386
387
    mCatList->clear();
    mCatList->addItems(categories);
    mCurrent->setCategoryList(categories);
388
}