File indexing completed on 2024-11-24 04:39:32

0001 /*
0002     This file is part of Contact Editor.
0003 
0004     SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "contacteditorwidget.h"
0010 
0011 #include "contacteditorpageplugin.h"
0012 #include "contactmetadatabase_p.h"
0013 #include "personaleditor/personaleditorwidget.h"
0014 
0015 #include <KLocalizedString>
0016 #include <KTextEdit>
0017 #include <QTabWidget>
0018 
0019 #include "addresseditor/addresseslocationwidget.h"
0020 #include "businesseditor/businesseditorwidget.h"
0021 #include "customfieldeditor/customfieldswidget.h"
0022 #include "generalinfoeditor/generalinfowidget.h"
0023 #include <QCoreApplication>
0024 #include <QDirIterator>
0025 #include <QPluginLoader>
0026 #include <QVBoxLayout>
0027 
0028 class ContactEditorWidgetPrivate
0029 {
0030 public:
0031     ContactEditorWidgetPrivate(ContactEditorWidget::DisplayMode displayMode, ContactEditorWidget *parent)
0032         : mDisplayMode(displayMode)
0033         , mParent(parent)
0034     {
0035     }
0036 
0037     void initGui();
0038     void initGuiContactTab();
0039     void initGuiLocationTab();
0040     void initGuiBusinessTab();
0041     void initGuiPersonalTab();
0042     void initGuiNotesTab();
0043     void initGuiCustomFieldsTab();
0044 
0045     void loadCustomPages();
0046 
0047     QString loadCustom(const KContacts::Addressee &contact, const QString &key) const;
0048     void storeCustom(KContacts::Addressee &contact, const QString &key, const QString &value) const;
0049 
0050     ContactEditorWidget::DisplayMode mDisplayMode;
0051     ContactEditorWidget *const mParent;
0052     QTabWidget *mTabWidget = nullptr;
0053 
0054     Akonadi::GeneralInfoWidget *mGeneralInfoWidget = nullptr;
0055 
0056     // widgets from addresses group
0057     Akonadi::AddressesLocationWidget *mAddressesLocationWidget = nullptr;
0058 
0059     Akonadi::BusinessEditorWidget *mBusinessEditorWidget = nullptr;
0060 
0061     // widgets from notes group
0062     KTextEdit *mNotesWidget = nullptr;
0063 
0064     Akonadi::PersonalEditorWidget *mPersonalEditorWidget = nullptr;
0065 
0066     // widgets from custom fields group
0067     Akonadi::CustomFieldsWidget *mCustomFieldsWidget = nullptr;
0068 
0069     // custom editor pages
0070     QList<Akonadi::ContactEditorPagePlugin *> mCustomPages;
0071 };
0072 
0073 void ContactEditorWidgetPrivate::initGui()
0074 {
0075     auto layout = new QVBoxLayout(mParent);
0076     layout->setContentsMargins({});
0077 
0078     mTabWidget = new QTabWidget(mParent);
0079     layout->addWidget(mTabWidget);
0080 
0081     initGuiContactTab();
0082     initGuiLocationTab();
0083     initGuiBusinessTab();
0084     initGuiPersonalTab();
0085     initGuiNotesTab();
0086     if (mDisplayMode == ContactEditorWidget::FullMode) {
0087         initGuiCustomFieldsTab();
0088         loadCustomPages();
0089     }
0090 }
0091 
0092 void ContactEditorWidgetPrivate::initGuiContactTab()
0093 {
0094     mGeneralInfoWidget = new Akonadi::GeneralInfoWidget;
0095     mTabWidget->addTab(mGeneralInfoWidget, i18nc("@title:tab", "Contact"));
0096 }
0097 
0098 void ContactEditorWidgetPrivate::initGuiLocationTab()
0099 {
0100     mAddressesLocationWidget = new Akonadi::AddressesLocationWidget;
0101     mTabWidget->addTab(mAddressesLocationWidget, i18nc("@title:tab", "Location"));
0102 }
0103 
0104 void ContactEditorWidgetPrivate::initGuiBusinessTab()
0105 {
0106     mBusinessEditorWidget = new Akonadi::BusinessEditorWidget();
0107     mTabWidget->addTab(mBusinessEditorWidget, i18nc("@title:tab", "Business"));
0108 }
0109 
0110 void ContactEditorWidgetPrivate::initGuiPersonalTab()
0111 {
0112     mPersonalEditorWidget = new Akonadi::PersonalEditorWidget;
0113     mTabWidget->addTab(mPersonalEditorWidget, i18nc("@title:tab Personal properties of a contact", "Personal"));
0114 }
0115 
0116 void ContactEditorWidgetPrivate::initGuiNotesTab()
0117 {
0118     auto widget = new QWidget;
0119     auto layout = new QVBoxLayout(widget);
0120 
0121     mTabWidget->addTab(widget, i18nc("@title:tab", "Notes"));
0122 
0123     mNotesWidget = new KTextEdit;
0124     mNotesWidget->setAcceptRichText(false);
0125     layout->addWidget(mNotesWidget);
0126 }
0127 
0128 void ContactEditorWidgetPrivate::initGuiCustomFieldsTab()
0129 {
0130     mCustomFieldsWidget = new Akonadi::CustomFieldsWidget(mParent);
0131     mTabWidget->addTab(mCustomFieldsWidget, i18nc("@title:tab", "Custom Fields"));
0132 }
0133 
0134 void ContactEditorWidgetPrivate::loadCustomPages()
0135 {
0136     qDeleteAll(mCustomPages);
0137     mCustomPages.clear();
0138 
0139     const QStringList pluginDirs = QCoreApplication::libraryPaths();
0140 
0141     for (const QString &dir : pluginDirs) {
0142         QDirIterator it(dir + QLatin1StringView("/pim6/contacteditor/editorpageplugins"), QDir::Files);
0143 
0144         while (it.hasNext()) {
0145             QPluginLoader loader(it.next());
0146             if (!loader.load()) {
0147                 continue;
0148             }
0149 
0150             Akonadi::ContactEditorPagePlugin *plugin = qobject_cast<Akonadi::ContactEditorPagePlugin *>(loader.instance());
0151             if (!plugin) {
0152                 continue;
0153             }
0154 
0155             mCustomPages.append(plugin);
0156         }
0157     }
0158 
0159     for (Akonadi::ContactEditorPagePlugin *plugin : std::as_const(mCustomPages)) {
0160         mTabWidget->addTab(plugin, plugin->title());
0161     }
0162 }
0163 
0164 QString ContactEditorWidgetPrivate::loadCustom(const KContacts::Addressee &contact, const QString &key) const
0165 {
0166     return contact.custom(QStringLiteral("KADDRESSBOOK"), key);
0167 }
0168 
0169 void ContactEditorWidgetPrivate::storeCustom(KContacts::Addressee &contact, const QString &key, const QString &value) const
0170 {
0171     if (value.isEmpty()) {
0172         contact.removeCustom(QStringLiteral("KADDRESSBOOK"), key);
0173     } else {
0174         contact.insertCustom(QStringLiteral("KADDRESSBOOK"), key, value);
0175     }
0176 }
0177 
0178 ContactEditorWidget::ContactEditorWidget(QWidget *parent)
0179     : d(new ContactEditorWidgetPrivate(FullMode, this))
0180 {
0181     Q_UNUSED(parent)
0182     d->initGui();
0183 }
0184 
0185 ContactEditorWidget::ContactEditorWidget(ContactEditorWidget::DisplayMode displayMode, QWidget *parent)
0186     : d(new ContactEditorWidgetPrivate(displayMode, this))
0187 {
0188     Q_UNUSED(parent)
0189     d->initGui();
0190 }
0191 
0192 ContactEditorWidget::~ContactEditorWidget() = default;
0193 
0194 void ContactEditorWidget::loadContact(const KContacts::Addressee &contact, const Akonadi::ContactMetaDataBase &metaData)
0195 {
0196     d->mGeneralInfoWidget->loadContact(contact);
0197 
0198     // address group
0199     d->mAddressesLocationWidget->loadContact(contact);
0200 
0201     // general group
0202     d->mBusinessEditorWidget->loadContact(contact);
0203     // notes group
0204     d->mNotesWidget->setPlainText(contact.note());
0205 
0206     d->mPersonalEditorWidget->loadContact(contact);
0207     d->mGeneralInfoWidget->setDisplayType((Akonadi::DisplayNameEditWidget::DisplayType)metaData.displayNameMode());
0208     if (d->mDisplayMode == FullMode) {
0209         // custom fields group
0210         d->mCustomFieldsWidget->setLocalCustomFieldDescriptions(metaData.customFieldDescriptions());
0211         d->mCustomFieldsWidget->loadContact(contact);
0212 
0213         // custom pages
0214         for (Akonadi::ContactEditorPagePlugin *plugin : std::as_const(d->mCustomPages)) {
0215             plugin->loadContact(contact);
0216         }
0217     }
0218 }
0219 
0220 void ContactEditorWidget::storeContact(KContacts::Addressee &contact, Akonadi::ContactMetaDataBase &metaData) const
0221 {
0222     d->mGeneralInfoWidget->storeContact(contact);
0223 
0224     // address group
0225     d->mAddressesLocationWidget->storeContact(contact);
0226 
0227     // general group
0228     d->mBusinessEditorWidget->storeContact(contact);
0229 
0230     // notes group
0231     contact.setNote(d->mNotesWidget->toPlainText());
0232     d->mPersonalEditorWidget->storeContact(contact);
0233 
0234     if (d->mDisplayMode == FullMode) {
0235         // custom fields group
0236         d->mCustomFieldsWidget->storeContact(contact);
0237         metaData.setCustomFieldDescriptions(d->mCustomFieldsWidget->localCustomFieldDescriptions());
0238 
0239         metaData.setDisplayNameMode(d->mGeneralInfoWidget->displayType());
0240 
0241         // custom pages
0242         for (Akonadi::ContactEditorPagePlugin *plugin : std::as_const(d->mCustomPages)) {
0243             plugin->storeContact(contact);
0244         }
0245     }
0246 }
0247 
0248 void ContactEditorWidget::setReadOnly(bool readOnly)
0249 {
0250     d->mGeneralInfoWidget->setReadOnly(readOnly);
0251     // widgets from addresses group
0252     d->mAddressesLocationWidget->setReadOnly(readOnly);
0253 
0254     // widgets from general group
0255     d->mBusinessEditorWidget->setReadOnly(readOnly);
0256 
0257     // widgets from notes group
0258     d->mNotesWidget->setReadOnly(readOnly);
0259 
0260     d->mPersonalEditorWidget->setReadOnly(readOnly);
0261     if (d->mDisplayMode == FullMode) {
0262         // widgets from custom fields group
0263         d->mCustomFieldsWidget->setReadOnly(readOnly);
0264 
0265         // custom pages
0266         for (Akonadi::ContactEditorPagePlugin *plugin : std::as_const(d->mCustomPages)) {
0267             plugin->setReadOnly(readOnly);
0268         }
0269     }
0270 }
0271 
0272 bool ContactEditorWidget::hasNoSavedData() const
0273 {
0274     return d->mAddressesLocationWidget->hasNoSavedData();
0275 }
0276 
0277 #include "moc_contacteditorwidget.cpp"