1/*
2 Copyright (c) 2007 Volker Krause <vkrause@kde.org>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#include "subscriptiondialog_p.h"
21
22#include "control.h"
23#include "recursivecollectionfilterproxymodel.h"
24#include "subscriptionjob_p.h"
25#include "subscriptionmodel_p.h"
26
27#include <kdebug.h>
28#include <kglobal.h>
29#include <ksharedconfig.h>
30
31#include <klocalizedstring.h>
32
33#include <QVBoxLayout>
34#include <QHBoxLayout>
35
36#ifndef KDEPIM_MOBILE_UI
37#include <klineedit.h>
38#include <KPushButton>
39#include <krecursivefilterproxymodel.h>
40#include <QHeaderView>
41#include <QLabel>
42#include <QTreeView>
43#include <QCheckBox>
44#else
45#include <kdescendantsproxymodel.h>
46#include <QListView>
47#include <QSortFilterProxyModel>
48
49class CheckableFilterProxyModel : public QSortFilterProxyModel
50{
51public:
52 CheckableFilterProxyModel(QObject *parent = 0)
53 : QSortFilterProxyModel(parent)
54 {
55 }
56
57protected:
58 /*reimp*/
59 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
60 {
61 QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent);
62 return sourceModel()->flags(sourceIndex) &Qt::ItemIsUserCheckable;
63 }
64};
65#endif
66
67using namespace Akonadi;
68
69/**
70 * @internal
71 */
72class SubscriptionDialog::Private
73{
74public:
75 Private(SubscriptionDialog *parent)
76 : q(parent)
77 {
78 }
79
80 void done()
81 {
82 SubscriptionJob *job = new SubscriptionJob(q);
83 job->subscribe(model->subscribed());
84 job->unsubscribe(model->unsubscribed());
85 connect(job, SIGNAL(result(KJob*)), q, SLOT(subscriptionResult(KJob*)));
86 }
87
88 void subscriptionResult(KJob *job)
89 {
90 if (job->error()) {
91 // TODO
92 kWarning() << job->errorString();
93 }
94 q->deleteLater();
95 }
96
97 void modelLoaded()
98 {
99 collectionView->setEnabled(true);
100#ifndef KDEPIM_MOBILE_UI
101 collectionView->expandAll();
102#endif
103 q->enableButtonOk(true);
104 }
105
106 void slotSetPattern(const QString &text)
107 {
108 filterRecursiveCollectionFilter->setSearchPattern(text);
109#ifndef KDEPIM_MOBILE_UI
110 collectionView->expandAll();
111#endif
112 }
113
114 void slotSetIncludeCheckedOnly(bool checked)
115 {
116 filterRecursiveCollectionFilter->setIncludeCheckedOnly(checked);
117 }
118
119 void writeConfig()
120 {
121 KConfigGroup group(KGlobal::config(), "SubscriptionDialog");
122 group.writeEntry("Size", q->size());
123 }
124
125 void readConfig()
126 {
127 KConfigGroup group(KGlobal::config(), "SubscriptionDialog");
128 const QSize sizeDialog = group.readEntry("Size", QSize(300, 200));
129 if (sizeDialog.isValid()) {
130 q->resize(sizeDialog);
131 }
132 }
133
134 void slotUnSubscribe();
135 void slotSubscribe();
136
137 SubscriptionDialog *q;
138#ifndef KDEPIM_MOBILE_UI
139 QTreeView *collectionView;
140 KPushButton *subscribe;
141 KPushButton *unSubscribe;
142#else
143 QListView *collectionView;
144#endif
145 SubscriptionModel *model;
146 RecursiveCollectionFilterProxyModel *filterRecursiveCollectionFilter;
147
148};
149
150void SubscriptionDialog::Private::slotSubscribe()
151{
152#ifndef KDEPIM_MOBILE_UI
153 QModelIndexList list = collectionView->selectionModel()->selectedIndexes();
154 foreach (const QModelIndex &index, list) {
155 model->setData(index, Qt::Checked, Qt::CheckStateRole);
156 }
157 collectionView->setFocus();
158#endif
159}
160
161void SubscriptionDialog::Private::slotUnSubscribe()
162{
163#ifndef KDEPIM_MOBILE_UI
164 QModelIndexList list = collectionView->selectionModel()->selectedIndexes();
165 foreach (const QModelIndex &index, list) {
166 model->setData(index, Qt::Unchecked, Qt::CheckStateRole);
167 }
168 collectionView->setFocus();
169#endif
170}
171
172SubscriptionDialog::SubscriptionDialog(QWidget *parent)
173 : KDialog(parent)
174 , d(new Private(this))
175{
176 init(QStringList());
177}
178
179SubscriptionDialog::SubscriptionDialog(const QStringList &mimetypes, QWidget *parent)
180 : KDialog(parent)
181 , d(new Private(this))
182{
183 init(mimetypes);
184}
185
186void SubscriptionDialog::showHiddenCollection(bool showHidden)
187{
188 d->model->showHiddenCollection(showHidden);
189}
190
191void SubscriptionDialog::init(const QStringList &mimetypes)
192{
193 enableButtonOk(false);
194 setCaption(i18n("Local Subscriptions"));
195 QWidget *mainWidget = new QWidget(this);
196 QVBoxLayout *mainLayout = new QVBoxLayout;
197 mainWidget->setLayout(mainLayout);
198 setMainWidget(mainWidget);
199
200 d->model = new SubscriptionModel(this);
201
202#ifndef KDEPIM_MOBILE_UI
203 d->filterRecursiveCollectionFilter
204 = new Akonadi::RecursiveCollectionFilterProxyModel(this);
205 d->filterRecursiveCollectionFilter->setDynamicSortFilter(true);
206 d->filterRecursiveCollectionFilter->setSourceModel(d->model);
207 d->filterRecursiveCollectionFilter->setFilterCaseSensitivity(Qt::CaseInsensitive);
208 if (!mimetypes.isEmpty()) {
209 d->filterRecursiveCollectionFilter->addContentMimeTypeInclusionFilters(mimetypes);
210 }
211
212 d->collectionView = new QTreeView(mainWidget);
213 d->collectionView->setEditTriggers(QAbstractItemView::NoEditTriggers);
214 d->collectionView->header()->hide();
215 d->collectionView->setModel(d->filterRecursiveCollectionFilter);
216 d->collectionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
217
218 QHBoxLayout *filterBarLayout = new QHBoxLayout;
219
220 filterBarLayout->addWidget(new QLabel(i18n("Search:")));
221
222 KLineEdit *lineEdit = new KLineEdit(mainWidget);
223 lineEdit->setClearButtonShown(true);
224 lineEdit->setFocus();
225 connect(lineEdit, SIGNAL(textChanged(QString)),
226 this, SLOT(slotSetPattern(QString)));
227 filterBarLayout->addWidget(lineEdit);
228 QCheckBox *checkBox = new QCheckBox(i18n("Subscribed only"), mainWidget);
229 connect(checkBox, SIGNAL(clicked(bool)),
230 this, SLOT(slotSetIncludeCheckedOnly(bool)));
231 filterBarLayout->addWidget(checkBox);
232
233 QHBoxLayout *hboxLayout = new QHBoxLayout;
234 hboxLayout->addWidget(d->collectionView);
235
236 QVBoxLayout *subscribeButtonLayout = new QVBoxLayout;
237 d->subscribe = new KPushButton(i18n("Subscribe"));
238 subscribeButtonLayout->addWidget(d->subscribe);
239 connect(d->subscribe, SIGNAL(clicked()), this, SLOT(slotSubscribe()));
240
241 d->unSubscribe = new KPushButton(i18n("Unsubscribe"));
242 subscribeButtonLayout->addWidget(d->unSubscribe);
243 connect(d->unSubscribe, SIGNAL(clicked()), this, SLOT(slotUnSubscribe()));
244 subscribeButtonLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Minimum, QSizePolicy::Expanding));
245
246 hboxLayout->addLayout(subscribeButtonLayout);
247
248 mainLayout->addLayout(filterBarLayout);
249 mainLayout->addLayout(hboxLayout);
250
251#else
252
253 d->filterRecursiveCollectionFilter
254 = new Akonadi::RecursiveCollectionFilterProxyModel(this);
255 if (!mimetypes.isEmpty()) {
256 d->filterRecursiveCollectionFilter->addContentMimeTypeInclusionFilters(mimetypes);
257 }
258
259 d->filterRecursiveCollectionFilter->setSourceModel(d->model);
260
261 KDescendantsProxyModel *flatModel = new KDescendantsProxyModel(this);
262 flatModel->setDisplayAncestorData(true);
263 flatModel->setAncestorSeparator(QLatin1String("/"));
264 flatModel->setSourceModel(d->filterRecursiveCollectionFilter);
265
266 CheckableFilterProxyModel *checkableModel = new CheckableFilterProxyModel(this);
267 checkableModel->setSourceModel(flatModel);
268
269 d->collectionView = new QListView(mainWidget);
270
271 d->collectionView->setModel(checkableModel);
272 mainLayout->addWidget(d->collectionView);
273#endif
274
275 connect(d->model, SIGNAL(loaded()), SLOT(modelLoaded()));
276 connect(this, SIGNAL(okClicked()), SLOT(done()));
277 connect(this, SIGNAL(cancelClicked()), SLOT(deleteLater()));
278 Control::widgetNeedsAkonadi(mainWidget);
279 d->readConfig();
280}
281
282SubscriptionDialog::~SubscriptionDialog()
283{
284 d->writeConfig();
285 delete d;
286}
287
288#include "moc_subscriptiondialog_p.cpp"
289