1 /*
2     This file is part of Contact Editor.
3 
4     SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "contacteditorwidget.h"
10 #include "config-contact-editor.h"
11 
12 #include "contacteditorpageplugin.h"
13 #include "contactmetadatabase_p.h"
14 #include "personaleditor/personaleditorwidget.h"
15 
16 #include <KConfig>
17 #include <KLocalizedString>
18 #include <KTextEdit>
19 #include <QTabWidget>
20 
21 #include "addresseditor/addresseslocationwidget.h"
22 #include "businesseditor/businesseditorwidget.h"
23 #include "customfieldeditor/customfieldswidget.h"
24 #include "generalinfoeditor/generalinfowidget.h"
25 #include <QDirIterator>
26 #include <QPluginLoader>
27 #include <QVBoxLayout>
28 
29 class ContactEditorWidgetPrivate
30 {
31 public:
ContactEditorWidgetPrivate(ContactEditorWidget::DisplayMode displayMode,ContactEditorWidget * parent)32     ContactEditorWidgetPrivate(ContactEditorWidget::DisplayMode displayMode, ContactEditorWidget *parent)
33         : mDisplayMode(displayMode)
34         , mParent(parent)
35     {
36     }
37 
38     void initGui();
39     void initGuiContactTab();
40     void initGuiLocationTab();
41     void initGuiBusinessTab();
42     void initGuiPersonalTab();
43     void initGuiNotesTab();
44     void initGuiCustomFieldsTab();
45 
46     void loadCustomPages();
47 
48     QString loadCustom(const KContacts::Addressee &contact, const QString &key) const;
49     void storeCustom(KContacts::Addressee &contact, const QString &key, const QString &value) const;
50 
51     ContactEditorWidget::DisplayMode mDisplayMode;
52     ContactEditorWidget *const mParent;
53     QTabWidget *mTabWidget = nullptr;
54 
55     ContactEditor::GeneralInfoWidget *mGeneralInfoWidget = nullptr;
56 
57     // widgets from addresses group
58     ContactEditor::AddressesLocationWidget *mAddressesLocationWidget = nullptr;
59 
60     ContactEditor::BusinessEditorWidget *mBusinessEditorWidget = nullptr;
61 
62     // widgets from notes group
63     KTextEdit *mNotesWidget = nullptr;
64 
65     ContactEditor::PersonalEditorWidget *mPersonalEditorWidget = nullptr;
66 
67     // widgets from custom fields group
68     ContactEditor::CustomFieldsWidget *mCustomFieldsWidget = nullptr;
69 
70     // custom editor pages
71     QList<ContactEditor::ContactEditorPagePlugin *> mCustomPages;
72 };
73 
initGui()74 void ContactEditorWidgetPrivate::initGui()
75 {
76     auto layout = new QVBoxLayout(mParent);
77     layout->setContentsMargins({});
78 
79     mTabWidget = new QTabWidget(mParent);
80     layout->addWidget(mTabWidget);
81 
82     initGuiContactTab();
83     initGuiLocationTab();
84     initGuiBusinessTab();
85     initGuiPersonalTab();
86     initGuiNotesTab();
87     if (mDisplayMode == ContactEditorWidget::FullMode) {
88         initGuiCustomFieldsTab();
89         loadCustomPages();
90     }
91 }
92 
initGuiContactTab()93 void ContactEditorWidgetPrivate::initGuiContactTab()
94 {
95     mGeneralInfoWidget = new ContactEditor::GeneralInfoWidget;
96     mTabWidget->addTab(mGeneralInfoWidget, i18nc("@title:tab", "Contact"));
97 }
98 
initGuiLocationTab()99 void ContactEditorWidgetPrivate::initGuiLocationTab()
100 {
101     mAddressesLocationWidget = new ContactEditor::AddressesLocationWidget;
102     mTabWidget->addTab(mAddressesLocationWidget, i18nc("@title:tab", "Location"));
103 }
104 
initGuiBusinessTab()105 void ContactEditorWidgetPrivate::initGuiBusinessTab()
106 {
107     mBusinessEditorWidget = new ContactEditor::BusinessEditorWidget();
108     mTabWidget->addTab(mBusinessEditorWidget, i18nc("@title:tab", "Business"));
109 }
110 
initGuiPersonalTab()111 void ContactEditorWidgetPrivate::initGuiPersonalTab()
112 {
113     mPersonalEditorWidget = new ContactEditor::PersonalEditorWidget;
114     mTabWidget->addTab(mPersonalEditorWidget, i18nc("@title:tab Personal properties of a contact", "Personal"));
115 }
116 
initGuiNotesTab()117 void ContactEditorWidgetPrivate::initGuiNotesTab()
118 {
119     auto widget = new QWidget;
120     auto layout = new QVBoxLayout(widget);
121 
122     mTabWidget->addTab(widget, i18nc("@title:tab", "Notes"));
123 
124     mNotesWidget = new KTextEdit;
125     mNotesWidget->setAcceptRichText(false);
126     layout->addWidget(mNotesWidget);
127 }
128 
initGuiCustomFieldsTab()129 void ContactEditorWidgetPrivate::initGuiCustomFieldsTab()
130 {
131     mCustomFieldsWidget = new ContactEditor::CustomFieldsWidget(mParent);
132     mTabWidget->addTab(mCustomFieldsWidget, i18nc("@title:tab", "Custom Fields"));
133 }
134 
loadCustomPages()135 void ContactEditorWidgetPrivate::loadCustomPages()
136 {
137     qDeleteAll(mCustomPages);
138     mCustomPages.clear();
139 
140     const QString pluginDirectory = QStringLiteral("%1/contacteditor/editorpageplugins/").arg(QStringLiteral(EDITOR_CONTACT_LIB));
141     QDirIterator it(pluginDirectory, QDir::Files);
142 
143     while (it.hasNext()) {
144         QPluginLoader loader(it.next());
145         if (!loader.load()) {
146             continue;
147         }
148 
149         ContactEditor::ContactEditorPagePlugin *plugin = qobject_cast<ContactEditor::ContactEditorPagePlugin *>(loader.instance());
150         if (!plugin) {
151             continue;
152         }
153 
154         mCustomPages.append(plugin);
155     }
156 
157     for (ContactEditor::ContactEditorPagePlugin *plugin : std::as_const(mCustomPages)) {
158         mTabWidget->addTab(plugin, plugin->title());
159     }
160 }
161 
loadCustom(const KContacts::Addressee & contact,const QString & key) const162 QString ContactEditorWidgetPrivate::loadCustom(const KContacts::Addressee &contact, const QString &key) const
163 {
164     return contact.custom(QStringLiteral("KADDRESSBOOK"), key);
165 }
166 
storeCustom(KContacts::Addressee & contact,const QString & key,const QString & value) const167 void ContactEditorWidgetPrivate::storeCustom(KContacts::Addressee &contact, const QString &key, const QString &value) const
168 {
169     if (value.isEmpty()) {
170         contact.removeCustom(QStringLiteral("KADDRESSBOOK"), key);
171     } else {
172         contact.insertCustom(QStringLiteral("KADDRESSBOOK"), key, value);
173     }
174 }
175 
ContactEditorWidget(QWidget * parent)176 ContactEditorWidget::ContactEditorWidget(QWidget *parent)
177     : d(new ContactEditorWidgetPrivate(FullMode, this))
178 {
179     Q_UNUSED(parent)
180     d->initGui();
181 }
182 
ContactEditorWidget(ContactEditorWidget::DisplayMode displayMode,QWidget * parent)183 ContactEditorWidget::ContactEditorWidget(ContactEditorWidget::DisplayMode displayMode, QWidget *parent)
184     : d(new ContactEditorWidgetPrivate(displayMode, this))
185 {
186     Q_UNUSED(parent)
187     d->initGui();
188 }
189 
190 ContactEditorWidget::~ContactEditorWidget() = default;
191 
loadContact(const KContacts::Addressee & contact,const ContactEditor::ContactMetaDataBase & metaData)192 void ContactEditorWidget::loadContact(const KContacts::Addressee &contact, const ContactEditor::ContactMetaDataBase &metaData)
193 {
194     d->mGeneralInfoWidget->loadContact(contact);
195 
196     // address group
197     d->mAddressesLocationWidget->loadContact(contact);
198 
199     // general group
200     d->mBusinessEditorWidget->loadContact(contact);
201     // notes group
202     d->mNotesWidget->setPlainText(contact.note());
203 
204     d->mPersonalEditorWidget->loadContact(contact);
205     d->mGeneralInfoWidget->setDisplayType((DisplayNameEditWidget::DisplayType)metaData.displayNameMode());
206     if (d->mDisplayMode == FullMode) {
207         // custom fields group
208         d->mCustomFieldsWidget->setLocalCustomFieldDescriptions(metaData.customFieldDescriptions());
209         d->mCustomFieldsWidget->loadContact(contact);
210 
211         // custom pages
212         for (ContactEditor::ContactEditorPagePlugin *plugin : std::as_const(d->mCustomPages)) {
213             plugin->loadContact(contact);
214         }
215     }
216 }
217 
storeContact(KContacts::Addressee & contact,ContactEditor::ContactMetaDataBase & metaData) const218 void ContactEditorWidget::storeContact(KContacts::Addressee &contact, ContactEditor::ContactMetaDataBase &metaData) const
219 {
220     d->mGeneralInfoWidget->storeContact(contact);
221 
222     // address group
223     d->mAddressesLocationWidget->storeContact(contact);
224 
225     // general group
226     d->mBusinessEditorWidget->storeContact(contact);
227 
228     // notes group
229     contact.setNote(d->mNotesWidget->toPlainText());
230     d->mPersonalEditorWidget->storeContact(contact);
231 
232     if (d->mDisplayMode == FullMode) {
233         // custom fields group
234         d->mCustomFieldsWidget->storeContact(contact);
235         metaData.setCustomFieldDescriptions(d->mCustomFieldsWidget->localCustomFieldDescriptions());
236 
237         metaData.setDisplayNameMode(d->mGeneralInfoWidget->displayType());
238 
239         // custom pages
240         for (ContactEditor::ContactEditorPagePlugin *plugin : std::as_const(d->mCustomPages)) {
241             plugin->storeContact(contact);
242         }
243     }
244 }
245 
setReadOnly(bool readOnly)246 void ContactEditorWidget::setReadOnly(bool readOnly)
247 {
248     d->mGeneralInfoWidget->setReadOnly(readOnly);
249     // widgets from addresses group
250     d->mAddressesLocationWidget->setReadOnly(readOnly);
251 
252     // widgets from general group
253     d->mBusinessEditorWidget->setReadOnly(readOnly);
254 
255     // widgets from notes group
256     d->mNotesWidget->setReadOnly(readOnly);
257 
258     d->mPersonalEditorWidget->setReadOnly(readOnly);
259     if (d->mDisplayMode == FullMode) {
260         // widgets from custom fields group
261         d->mCustomFieldsWidget->setReadOnly(readOnly);
262 
263         // custom pages
264         for (ContactEditor::ContactEditorPagePlugin *plugin : std::as_const(d->mCustomPages)) {
265             plugin->setReadOnly(readOnly);
266         }
267     }
268 }
269 
hasNoSavedData() const270 bool ContactEditorWidget::hasNoSavedData() const
271 {
272     return d->mAddressesLocationWidget->hasNoSavedData();
273 }
274