Fix Bug 358840 - kmail composer: menu item "send" missing
[kdepim.git] / knotes / configdialog / knotecollectionconfigwidget.cpp
blobec67849ad6e536c3797cbfe17f5fdaa38f03ebd6
1 /*
2 Copyright (C) 2013-2015 Laurent Montel <montel@kde.org>
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.
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.
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.
20 #include "knotecollectionconfigwidget.h"
21 #include "NoteShared/ShowFolderNotesAttribute"
22 #include <Akonadi/Notes/NoteUtils>
23 #include "notesharedglobalconfig.h"
24 #include "AkonadiWidgets/ManageAccountWidget"
26 #include <AkonadiCore/CollectionModifyJob>
27 #include <AkonadiCore/CollectionFilterProxyModel>
28 #include <KRecursiveFilterProxyModel>
29 #include <QInputDialog>
31 #include <AkonadiWidgets/CollectionRequester>
32 #include <AkonadiCore/ChangeRecorder>
33 #include <AkonadiCore/EntityTreeModel>
34 #include <AkonadiCore/Collection>
35 #include <AkonadiWidgets/EntityTreeView>
36 #include <AkonadiCore/EntityDisplayAttribute>
38 #include <KMime/Message>
40 #include <KCheckableProxyModel>
42 #include <KLocalizedString>
43 #include <QPushButton>
44 #include <QLineEdit>
45 #include "knotes_debug.h"
46 #include <KMessageBox>
48 #include <QVBoxLayout>
49 #include <QHBoxLayout>
50 #include <QLabel>
51 #include <QTimer>
53 KNoteCollectionConfigWidget::KNoteCollectionConfigWidget(QWidget *parent)
54 : QWidget(parent),
55 mCanUpdateStatus(false)
57 QHBoxLayout *mainLayout = new QHBoxLayout;
58 setLayout(mainLayout);
60 QTabWidget *tabWidget = new QTabWidget;
61 mainLayout->addWidget(tabWidget);
63 QWidget *collectionWidget = new QWidget;
64 QVBoxLayout *vbox = new QVBoxLayout;
65 collectionWidget->setLayout(vbox);
66 tabWidget->addTab(collectionWidget, i18n("Folders"));
68 QLabel *label = new QLabel(i18n("Select which KNotes folders to show:"));
69 vbox->addWidget(label);
71 // Create a new change recorder.
72 mChangeRecorder = new Akonadi::ChangeRecorder(this);
73 mChangeRecorder->setMimeTypeMonitored(Akonadi::NoteUtils::noteMimeType());
74 mChangeRecorder->fetchCollection(true);
75 mChangeRecorder->setAllMonitored(true);
77 mModel = new Akonadi::EntityTreeModel(mChangeRecorder, this);
78 // Set the model to show only collections, not items.
79 mModel->setItemPopulationStrategy(Akonadi::EntityTreeModel::NoItemPopulation);
81 Akonadi::CollectionFilterProxyModel *mimeTypeProxy = new Akonadi::CollectionFilterProxyModel(this);
82 mimeTypeProxy->setExcludeVirtualCollections(true);
83 mimeTypeProxy->addMimeTypeFilters(QStringList() << Akonadi::NoteUtils::noteMimeType());
84 mimeTypeProxy->setSourceModel(mModel);
86 // Create the Check proxy model.
87 mSelectionModel = new QItemSelectionModel(mimeTypeProxy);
88 mCheckProxy = new KCheckableProxyModel(this);
89 mCheckProxy->setSelectionModel(mSelectionModel);
90 mCheckProxy->setSourceModel(mimeTypeProxy);
92 connect(mModel, &Akonadi::EntityTreeModel::rowsInserted, this, &KNoteCollectionConfigWidget::slotCollectionsInserted);
94 connect(mCheckProxy, &KCheckableProxyModel::dataChanged, this, &KNoteCollectionConfigWidget::slotDataChanged);
95 mCollectionFilter = new KRecursiveFilterProxyModel(this);
96 mCollectionFilter->setSourceModel(mCheckProxy);
97 mCollectionFilter->setDynamicSortFilter(true);
98 mCollectionFilter->setFilterCaseSensitivity(Qt::CaseInsensitive);
100 QLineEdit *searchLine = new QLineEdit(this);
101 searchLine->setPlaceholderText(i18n("Search..."));
102 searchLine->setClearButtonEnabled(true);
103 connect(searchLine, &QLineEdit::textChanged, this, &KNoteCollectionConfigWidget::slotSetCollectionFilter);
105 vbox->addWidget(searchLine);
107 mFolderView = new Akonadi::EntityTreeView(this);
108 mFolderView->setDragEnabled(false);
109 mFolderView->setEditTriggers(QAbstractItemView::NoEditTriggers);
110 mFolderView->setAlternatingRowColors(true);
111 vbox->addWidget(mFolderView);
113 mFolderView->setModel(mCollectionFilter);
114 connect(mFolderView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KNoteCollectionConfigWidget::slotUpdateButtons);
116 QHBoxLayout *hbox = new QHBoxLayout;
117 vbox->addLayout(hbox);
119 QPushButton *button = new QPushButton(i18n("&Select All"), this);
120 connect(button, &QPushButton::clicked, this, &KNoteCollectionConfigWidget::slotSelectAllCollections);
121 hbox->addWidget(button);
123 button = new QPushButton(i18n("&Unselect All"), this);
124 connect(button, &QPushButton::clicked, this, &KNoteCollectionConfigWidget::slotUnselectAllCollections);
125 hbox->addWidget(button);
126 hbox->addStretch(1);
128 mRenameCollection = new QPushButton(i18n("Rename notes..."), this);
129 connect(mRenameCollection, &QPushButton::clicked, this, &KNoteCollectionConfigWidget::slotRenameCollection);
130 hbox->addWidget(mRenameCollection);
132 vbox->addWidget(new QLabel(i18nc("@info", "Select the folder where the note will be saved:")));
133 mDefaultSaveFolder = new Akonadi::CollectionRequester(Akonadi::Collection(NoteShared::NoteSharedGlobalConfig::self()->defaultFolder()));
134 mDefaultSaveFolder->setMimeTypeFilter(QStringList() << Akonadi::NoteUtils::noteMimeType());
135 mDefaultSaveFolder->setContentMimeTypes(QStringList() << QStringLiteral("application/x-vnd.akonadi.note")
136 << QStringLiteral("text/x-vnd.akonadi.note")
137 << QStringLiteral("inode/directory"));
138 Akonadi::CollectionDialog::CollectionDialogOptions options;
139 options |= Akonadi::CollectionDialog::AllowToCreateNewChildCollection;
140 options |= Akonadi::CollectionDialog::KeepTreeExpanded;
141 mDefaultSaveFolder->changeCollectionDialogOptions(options);
142 connect(mDefaultSaveFolder, &Akonadi::CollectionRequester::collectionChanged, this, &KNoteCollectionConfigWidget::slotDataChanged);
144 vbox->addWidget(mDefaultSaveFolder);
146 QWidget *accountWidget = new QWidget;
147 QVBoxLayout *vboxAccountWidget = new QVBoxLayout;
148 accountWidget->setLayout(vboxAccountWidget);
150 Akonadi::ManageAccountWidget *manageAccountWidget = new Akonadi::ManageAccountWidget(this);
151 vboxAccountWidget->addWidget(manageAccountWidget);
153 manageAccountWidget->setMimeTypeFilter(QStringList() << Akonadi::NoteUtils::noteMimeType());
154 manageAccountWidget->setCapabilityFilter(QStringList() << QStringLiteral("Resource")); // show only resources, no agents
155 tabWidget->addTab(accountWidget, i18n("Accounts"));
157 QTimer::singleShot(1000, this, &KNoteCollectionConfigWidget::slotUpdateCollectionStatus);
158 slotUpdateButtons();
161 KNoteCollectionConfigWidget::~KNoteCollectionConfigWidget()
166 void KNoteCollectionConfigWidget::slotUpdateButtons()
168 mRenameCollection->setEnabled(mFolderView->selectionModel()->hasSelection());
171 void KNoteCollectionConfigWidget::slotRenameCollection()
173 const QModelIndexList rows = mFolderView->selectionModel()->selectedRows();
175 if (rows.size() != 1) {
176 return;
179 QModelIndex idx = rows.at(0);
181 QString title = idx.data().toString();
183 Akonadi::Collection col = idx.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
184 Q_ASSERT(col.isValid());
185 if (!col.isValid()) {
186 return;
189 bool ok;
190 const QString name = QInputDialog::getText(this, i18n("Rename Notes"),
191 i18n("Name:"), QLineEdit::Normal, title, &ok);
193 if (ok) {
194 if (col.hasAttribute<Akonadi::EntityDisplayAttribute>() &&
195 !col.attribute<Akonadi::EntityDisplayAttribute>()->displayName().isEmpty()) {
196 col.attribute<Akonadi::EntityDisplayAttribute>()->setDisplayName(name);
197 } else if (!name.isEmpty()) {
198 col.setName(name);
201 Akonadi::CollectionModifyJob *job = new Akonadi::CollectionModifyJob(col, this);
202 connect(job, &Akonadi::CollectionModifyJob::result, this, &KNoteCollectionConfigWidget::slotCollectionModifyFinished);
203 job->start();
207 void KNoteCollectionConfigWidget::slotCollectionModifyFinished(KJob *job)
209 if (job->error()) {
210 KMessageBox::error(this, i18n("An error was occurred during renaming: %1", job->errorString()), i18n("Rename note"));
214 void KNoteCollectionConfigWidget::slotDataChanged()
216 Q_EMIT emitChanged(true);
219 void KNoteCollectionConfigWidget::slotSetCollectionFilter(const QString &filter)
221 mCollectionFilter->setFilterWildcard(filter);
222 mFolderView->expandAll();
225 void KNoteCollectionConfigWidget::slotUpdateCollectionStatus()
227 mCanUpdateStatus = true;
228 updateStatus(QModelIndex());
231 void KNoteCollectionConfigWidget::slotSelectAllCollections()
233 forceStatus(QModelIndex(), true);
234 Q_EMIT emitChanged(true);
237 void KNoteCollectionConfigWidget::slotUnselectAllCollections()
239 forceStatus(QModelIndex(), false);
240 Q_EMIT emitChanged(true);
243 void KNoteCollectionConfigWidget::updateStatus(const QModelIndex &parent)
245 if (!mCanUpdateStatus) {
246 return;
249 const int nbCol = mCheckProxy->rowCount(parent);
250 for (int i = 0; i < nbCol; ++i) {
251 const QModelIndex child = mCheckProxy->index(i, 0, parent);
253 const Akonadi::Collection collection =
254 mCheckProxy->data(child, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
256 NoteShared::ShowFolderNotesAttribute *attr = collection.attribute<NoteShared::ShowFolderNotesAttribute>();
257 if (attr) {
258 mCheckProxy->setData(child, Qt::Checked, Qt::CheckStateRole);
260 updateStatus(child);
264 void KNoteCollectionConfigWidget::forceStatus(const QModelIndex &parent, bool status)
266 const int nbCol = mCheckProxy->rowCount(parent);
267 for (int i = 0; i < nbCol; ++i) {
268 const QModelIndex child = mCheckProxy->index(i, 0, parent);
269 mCheckProxy->setData(child, status ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
270 forceStatus(child, status);
274 void KNoteCollectionConfigWidget::slotCollectionsInserted(const QModelIndex &, int, int)
276 mFolderView->expandAll();
279 void KNoteCollectionConfigWidget::save()
281 updateCollectionsRecursive(QModelIndex());
282 Akonadi::Collection col = mDefaultSaveFolder->collection();
283 if (col.isValid()) {
284 NoteShared::NoteSharedGlobalConfig::self()->setDefaultFolder(col.id());
285 NoteShared::NoteSharedGlobalConfig::self()->save();
289 void KNoteCollectionConfigWidget::updateCollectionsRecursive(const QModelIndex &parent)
291 const int nbCol = mCheckProxy->rowCount(parent);
292 for (int i = 0; i < nbCol; ++i) {
293 const QModelIndex child = mCheckProxy->index(i, 0, parent);
295 Akonadi::Collection collection =
296 mCheckProxy->data(child, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
298 NoteShared::ShowFolderNotesAttribute *attr = collection.attribute<NoteShared::ShowFolderNotesAttribute>();
299 Akonadi::CollectionModifyJob *modifyJob = 0;
300 const bool selected = (mCheckProxy->data(child, Qt::CheckStateRole).toInt() != 0);
301 if (selected && !attr) {
302 attr = collection.attribute<NoteShared::ShowFolderNotesAttribute>(Akonadi::Collection::AddIfMissing);
303 modifyJob = new Akonadi::CollectionModifyJob(collection);
304 modifyJob->setProperty("AttributeAdded", true);
305 } else if (!selected && attr) {
306 collection.removeAttribute<NoteShared::ShowFolderNotesAttribute>();
307 modifyJob = new Akonadi::CollectionModifyJob(collection);
308 modifyJob->setProperty("AttributeAdded", false);
311 if (modifyJob) {
312 connect(modifyJob, &Akonadi::CollectionModifyJob::finished, this, &KNoteCollectionConfigWidget::slotModifyJobDone);
314 updateCollectionsRecursive(child);
318 void KNoteCollectionConfigWidget::slotModifyJobDone(KJob *job)
320 Akonadi::CollectionModifyJob *modifyJob = qobject_cast<Akonadi::CollectionModifyJob *>(job);
321 if (modifyJob && job->error()) {
322 if (job->property("AttributeAdded").toBool()) {
323 qCWarning(KNOTES_LOG) << "Failed to append ShowFolderNotesAttribute to collection"
324 << modifyJob->collection().id() << ":"
325 << job->errorString();
326 } else {
327 qCWarning(KNOTES_LOG) << "Failed to remove ShowFolderNotesAttribute from collection"
328 << modifyJob->collection().id() << ":"
329 << job->errorString();