collectiongeneralpage.cpp 10.8 KB
Newer Older
1
/*
Laurent Montel's avatar
Laurent Montel committed
2
  SPDX-FileCopyrightText: 2009-2021 Laurent Montel <montel@kde.org>
3

4
  SPDX-License-Identifier: GPL-2.0-or-later
5
6
7
*/

#include "collectiongeneralpage.h"
8
#include "collectiongeneralwidget.h"
9
10
#include "collectiontypeutil.h"

11
#include "folder/foldersettings.h"
Laurent Montel's avatar
Laurent Montel committed
12
#include "incidencesforwidget.h"
13
#include "kernel/mailkernel.h"
Laurent Montel's avatar
Laurent Montel committed
14
#include "util/mailutil_p.h"
Laurent Montel's avatar
Laurent Montel committed
15
16
#include <PimCommonAkonadi/CollectionAnnotationsAttribute>
#include <PimCommonAkonadi/ContentTypeWidget>
17
18
19
20
21
22

#include <AgentManager>
#include <AttributeFactory>
#include <Collection>
#include <CollectionModifyJob>
#include <EntityDisplayAttribute>
Laurent Montel's avatar
Laurent Montel committed
23
#include <PimCommon/PimUtil>
Laurent Montel's avatar
Laurent Montel committed
24

25
#include <KIdentityManagement/IdentityCombo>
Laurent Montel's avatar
Laurent Montel committed
26
#include <Libkdepim/LineEditCatchReturnKey>
Laurent Montel's avatar
Laurent Montel committed
27
#include <PimCommonAkonadi/ImapResourceCapabilitiesManager>
28
29
30
31
32
33
34
35

#include <KColorScheme>
#include <KLocalizedString>
#include <KMessageBox>

#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
Laurent Montel's avatar
Laurent Montel committed
36
#include <QLineEdit>
37
38
39
40
41
42
#include <QVBoxLayout>

using namespace Akonadi;
using namespace MailCommon;

CollectionGeneralPage::CollectionGeneralPage(QWidget *parent)
Laurent Montel's avatar
Laurent Montel committed
43
    : CollectionPropertiesPage(parent)
44
45
46
47
48
49
50
51
52
53
54
{
    setObjectName(QStringLiteral("MailCommon::CollectionGeneralPage"));
    setPageTitle(i18nc("@title:tab General settings for a folder.", "General"));
}

CollectionGeneralPage::~CollectionGeneralPage()
{
}

void CollectionGeneralPage::init(const Akonadi::Collection &collection)
{
Laurent Montel's avatar
Laurent Montel committed
55
    mIsLocalSystemFolder = CommonKernel->isSystemFolderCollection(collection) || Kernel::folderIsInbox(collection);
56
57

    mIsResourceFolder = (collection.parentCollection() == Akonadi::Collection::root());
Laurent Montel's avatar
Laurent Montel committed
58
    QLabel *label = nullptr;
59

Laurent Montel's avatar
Laurent Montel committed
60
    auto topLayout = new QVBoxLayout(this);
61
62

    // Musn't be able to edit details for a non-resource, system folder.
Laurent Montel's avatar
Laurent Montel committed
63
    if ((!mIsLocalSystemFolder || mIsResourceFolder) && !mFolderCollection->isReadOnly()) {
Laurent Montel's avatar
Laurent Montel committed
64
        auto hl = new QHBoxLayout();
65
66
67
68
        topLayout->addItem(hl);
        label = new QLabel(i18nc("@label:textbox Name of the folder.", "&Name:"), this);
        hl->addWidget(label);

Laurent Montel's avatar
Laurent Montel committed
69
70
        mNameEdit = new QLineEdit(this);
        new KPIM::LineEditCatchReturnKey(mNameEdit, this);
71

Laurent Montel's avatar
Laurent Montel committed
72
        connect(mNameEdit, &QLineEdit::textChanged, this, &CollectionGeneralPage::slotNameChanged);
73
74
75
76
        label->setBuddy(mNameEdit);
        hl->addWidget(mNameEdit);
    }

77
78
    mCollectionGeneralWidget = new CollectionGeneralWidget(this);
    topLayout->addWidget(mCollectionGeneralWidget);
79
80
81
82
    // Only do make this settable, if the IMAP resource is enabled
    // and it's not the personal folders (those must not be changed)
    const QString collectionResource = collection.resource();
    if (CommonKernel->imapResourceManager()->hasAnnotationSupport(collectionResource)) {
83
        PimCommon::CollectionTypeUtil::FolderContentsType contentsType = PimCommon::CollectionTypeUtil::ContentsTypeMail;
84

Laurent Montel's avatar
Laurent Montel committed
85
        const auto *annotationAttribute = collection.attribute<PimCommon::CollectionAnnotationsAttribute>();
86

Laurent Montel's avatar
Laurent Montel committed
87
        const QMap<QByteArray, QByteArray> annotations = (annotationAttribute ? annotationAttribute->annotations() : QMap<QByteArray, QByteArray>());
88

89
        const bool sharedSeen = (annotations.value(PimCommon::CollectionTypeUtil::kolabSharedSeen()) == "true");
90

91
        PimCommon::CollectionTypeUtil collectionUtil;
Laurent Montel's avatar
Laurent Montel committed
92
93
        const PimCommon::CollectionTypeUtil::IncidencesFor incidencesFor =
            collectionUtil.incidencesForFromString(QLatin1String(annotations.value(PimCommon::CollectionTypeUtil::kolabIncidencesFor())));
94

Laurent Montel's avatar
Laurent Montel committed
95
96
        const PimCommon::CollectionTypeUtil::FolderContentsType folderType =
            collectionUtil.typeFromKolabName(annotations.value(PimCommon::CollectionTypeUtil::kolabFolderType()));
97

98
        int row = 0;
Laurent Montel's avatar
Laurent Montel committed
99
        auto gl = new QGridLayout();
100
        topLayout->addItem(gl);
101
        mContentsComboBox = new PimCommon::ContentTypeWidget(this);
102
103
104
        gl->addWidget(mContentsComboBox, row, 0, 1, 2);
        mContentsComboBox->setCurrentIndex(contentsType);

105
        connect(mContentsComboBox, &PimCommon::ContentTypeWidget::activated, this, &CollectionGeneralPage::slotFolderContentsSelectionChanged);
106
107
108
109
110
111
112
113

        if (mFolderCollection->isReadOnly() || mIsResourceFolder) {
            mContentsComboBox->setEnabled(false);
        }

        // Kolab incidences-for annotation.
        // Show incidences-for combobox if the contents type can be changed (new folder),
        // or if it's set to calendar or task (existing folder)
Laurent Montel's avatar
Laurent Montel committed
114
115
        const bool folderTypeComboboxEnabled =
            (folderType == PimCommon::CollectionTypeUtil::ContentsTypeCalendar || folderType == PimCommon::CollectionTypeUtil::ContentsTypeTask);
116
        ++row;
117
        mIncidencesForComboBox = new PimCommon::IncidencesForWidget(this);
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
        gl->addWidget(mIncidencesForComboBox, row, 0, 1, 2);

        mIncidencesForComboBox->setCurrentIndex(incidencesFor);
        mIncidencesForComboBox->setEnabled(folderTypeComboboxEnabled);

        mSharedSeenFlagsCheckBox = new QCheckBox(this);
        mSharedSeenFlagsCheckBox->setText(i18n("Share unread state with all users"));
        mSharedSeenFlagsCheckBox->setChecked(sharedSeen);
        ++row;
        gl->addWidget(mSharedSeenFlagsCheckBox, row, 0, 1, 1);
        mSharedSeenFlagsCheckBox->setWhatsThis(
            i18n("If enabled, the unread state of messages in this folder will be "
                 "the same for all users having access to this folder. If disabled "
                 "(the default), every user with access to this folder has their "
                 "own unread state."));
    }

Laurent Montel's avatar
Laurent Montel committed
135
    topLayout->addStretch(100); // eat all superfluous space
136
137
138
139
}

void CollectionGeneralPage::load(const Akonadi::Collection &collection)
{
140
    mFolderCollection = FolderSettings::forCollection(collection);
141
142
    init(collection);

143
    mCollectionGeneralWidget->load(collection);
144
145
146
147
148
149
150
151
152
    if (mNameEdit) {
        const QString displayName = collection.displayName();

        if (!mIsLocalSystemFolder || mIsResourceFolder) {
            mNameEdit->setText(displayName);
        }
    }

    if (mContentsComboBox) {
Laurent Montel's avatar
Laurent Montel committed
153
        const auto *annotationsAttribute = collection.attribute<PimCommon::CollectionAnnotationsAttribute>();
154
155
156

        if (annotationsAttribute) {
            const QMap<QByteArray, QByteArray> annotations = annotationsAttribute->annotations();
157
158
            if (annotations.contains(PimCommon::CollectionTypeUtil::kolabFolderType())) {
                PimCommon::CollectionTypeUtil collectionUtil;
Laurent Montel's avatar
Laurent Montel committed
159
                mContentsComboBox->setCurrentItem(collectionUtil.typeNameFromKolabType(annotations[PimCommon::CollectionTypeUtil::kolabFolderType()]));
160
161
162
163
164
165
166
167
168
169
            }
        }
    }
}

void CollectionGeneralPage::save(Collection &collection)
{
    if (mNameEdit) {
        if (!mIsLocalSystemFolder) {
            const QString nameFolder(mNameEdit->text().trimmed());
Laurent Montel's avatar
Laurent Montel committed
170
            bool canRenameFolder = !(nameFolder.startsWith(QLatin1Char('.')) || nameFolder.endsWith(QLatin1Char('.')) || nameFolder.contains(QLatin1Char('/'))
Laurent Montel's avatar
Laurent Montel committed
171
                                     || nameFolder.isEmpty());
172
173
174

            if (mIsResourceFolder && (PimCommon::Util::isImapResource(collection.resource()))) {
                collection.setName(nameFolder);
Laurent Montel's avatar
Laurent Montel committed
175
                Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
176
177
                instance.setName(nameFolder);
            } else if (canRenameFolder) {
Laurent Montel's avatar
Laurent Montel committed
178
179
                if (collection.hasAttribute<Akonadi::EntityDisplayAttribute>()
                    && !collection.attribute<Akonadi::EntityDisplayAttribute>()->displayName().isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
180
                    collection.attribute<Akonadi::EntityDisplayAttribute>()->setDisplayName(nameFolder);
181
182
183
184
185
186
                } else if (!nameFolder.isEmpty()) {
                    collection.setName(nameFolder);
                }
            }
        }
    }
187
    mCollectionGeneralWidget->save(collection);
188

Laurent Montel's avatar
Laurent Montel committed
189
    auto *annotationsAttribute = collection.attribute<PimCommon::CollectionAnnotationsAttribute>(Collection::AddIfMissing);
190
191
192

    QMap<QByteArray, QByteArray> annotations = annotationsAttribute->annotations();
    if (mSharedSeenFlagsCheckBox && mSharedSeenFlagsCheckBox->isEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
193
        annotations[PimCommon::CollectionTypeUtil::kolabSharedSeen()] = mSharedSeenFlagsCheckBox->isChecked() ? "true" : "false";
194
195
    }

196
    PimCommon::CollectionTypeUtil collectionUtil;
197
    if (mIncidencesForComboBox && mIncidencesForComboBox->isEnabled()) {
Laurent Montel's avatar
Laurent Montel committed
198
199
        annotations[PimCommon::CollectionTypeUtil::kolabIncidencesFor()] =
            collectionUtil.incidencesForToString(static_cast<PimCommon::CollectionTypeUtil::IncidencesFor>(mIncidencesForComboBox->currentIndex())).toLatin1();
200
201
202
    }

    if (mContentsComboBox) {
Laurent Montel's avatar
Laurent Montel committed
203
        const PimCommon::CollectionTypeUtil::FolderContentsType type = collectionUtil.contentsTypeFromString(mContentsComboBox->currentText());
204
205
206
207

        const QByteArray kolabName = collectionUtil.kolabNameFromType(type);
        if (!kolabName.isEmpty()) {
            const QString iconName = collectionUtil.iconNameFromContentsType(type);
Laurent Montel's avatar
Laurent Montel committed
208
            auto *attribute = collection.attribute<Akonadi::EntityDisplayAttribute>(Akonadi::Collection::AddIfMissing);
209
210
            attribute->setIconName(iconName);
            new Akonadi::CollectionModifyJob(collection);
Laurent Montel's avatar
Laurent Montel committed
211
            annotations[PimCommon::CollectionTypeUtil::kolabFolderType()] = kolabName;
212
213
214
        }
    }
    if (annotations.isEmpty()) {
215
        collection.removeAttribute<PimCommon::CollectionAnnotationsAttribute>();
216
217
218
219
220
221
222
    } else {
        annotationsAttribute->setAnnotations(annotations);
    }
}

void CollectionGeneralPage::slotFolderContentsSelectionChanged(int)
{
223
    PimCommon::CollectionTypeUtil collectionUtil;
Laurent Montel's avatar
Laurent Montel committed
224
    const PimCommon::CollectionTypeUtil::FolderContentsType type = collectionUtil.contentsTypeFromString(mContentsComboBox->currentText());
225

226
    if (type != PimCommon::CollectionTypeUtil::ContentsTypeMail) {
Laurent Montel's avatar
Laurent Montel committed
227
228
229
230
        const QString message = i18n(
            "You have configured this folder to contain groupware information. "
            "That means that this folder will disappear once the configuration "
            "dialog is closed.");
231
232
233
234

        KMessageBox::information(this, message);
    }

Laurent Montel's avatar
Laurent Montel committed
235
    const bool enable = (type == PimCommon::CollectionTypeUtil::ContentsTypeCalendar || type == PimCommon::CollectionTypeUtil::ContentsTypeTask);
236
237
238
239
240
241
242
243
244
245

    if (mIncidencesForComboBox) {
        mIncidencesForComboBox->setEnabled(enable);
    }
}

void CollectionGeneralPage::slotNameChanged(const QString &name)
{
#ifndef QT_NO_STYLE_STYLESHEET
    QString styleSheet;
Laurent Montel's avatar
Laurent Montel committed
246
    if (name.startsWith(QLatin1Char('.')) || name.endsWith(QLatin1Char('.')) || name.contains(QLatin1Char('/')) || name.trimmed().isEmpty()) {
247
248
249
        if (mColorName.isEmpty()) {
            const KColorScheme::BackgroundRole bgColorScheme(KColorScheme::NegativeBackground);
            KStatefulBrush bgBrush(KColorScheme::View, bgColorScheme);
250
            mColorName = bgBrush.brush(palette()).color().name();
251
        }
Laurent Montel's avatar
Laurent Montel committed
252
        styleSheet = QStringLiteral("QLineEdit{ background-color:%1 }").arg(mColorName);
253
254
255
256
    }
    setStyleSheet(styleSheet);
#endif
}