File indexing completed on 2024-05-19 04:29:32

0001 /* This file is part of the KDE project
0002    SPDX-FileCopyrightText: 2000 Simon Hausmann <hausmann@kde.org>
0003    SPDX-FileCopyrightText: 2006 Martin Pfeiffer <hubipete@gmx.net>
0004    SPDX-FileCopyrightText: 2012 C. Boemann <cbo@boemann.dk>
0005    SPDX-FileCopyrightText: 2017 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
0006 
0007    SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "KoConfigAuthorPage.h"
0011 
0012 #include "ui_KoConfigAuthorPage.h"
0013 
0014 #include <KoIcon.h>
0015 #include <QDebug>
0016 
0017 #include <klocalizedstring.h>
0018 #include <kuser.h>
0019 #include <kemailsettings.h>
0020 #include <kconfiggroup.h>
0021 #include <ksharedconfig.h>
0022 #include <KoResourcePaths.h>
0023 
0024 #include <QLineEdit>
0025 #include <QCompleter>
0026 #include <QStackedWidget>
0027 #include <QList>
0028 #include <QComboBox>
0029 #include <QGridLayout>
0030 #include <QString>
0031 #include <QStringList>
0032 #include <QToolButton>
0033 #include <QInputDialog>
0034 #include <QTableView>
0035 #include <QStandardItem>
0036 #include <QLabel>
0037 #include <QDomDocument>
0038 #include <QDomElement>
0039 #include <QFile>
0040 #include <QDir>
0041 #include <QByteArray>
0042 
0043 class Q_DECL_HIDDEN KoConfigAuthorPage::Private
0044 {
0045 public:
0046     QList<Ui::KoConfigAuthorPage *> profileUiList;
0047     QStackedWidget *stack;
0048     QComboBox *cmbAuthorProfiles;
0049     QToolButton *bnDeleteUser;
0050     QStringList positions;
0051     QStringList contactModes;
0052     QStringList contactKeys;
0053     QString defaultAuthor;
0054 };
0055 
0056 
0057 KoConfigAuthorPage::KoConfigAuthorPage()
0058         : d(new Private)
0059 {
0060     QGridLayout *layout = new QGridLayout(this);
0061 
0062     d->cmbAuthorProfiles = new QComboBox();
0063     layout->addWidget(d->cmbAuthorProfiles, 0, 0);
0064     QToolButton *newUser = new QToolButton();
0065     newUser->setIcon(koIcon("list-add"));
0066     newUser->setToolTip(i18n("Add new author profile (starts out as a copy of current)"));
0067     layout->addWidget(newUser, 0, 1);
0068     d->bnDeleteUser = new QToolButton();
0069     d->bnDeleteUser->setIcon(koIcon("edit-delete"));
0070     d->bnDeleteUser->setToolTip(i18n("Delete the author profile"));
0071     layout->addWidget(d->bnDeleteUser, 0, 2);
0072     QFrame *f = new QFrame();
0073     f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
0074     layout->addWidget(f, 1, 0);
0075     d->stack = new QStackedWidget();
0076     layout->addWidget(d->stack, 2, 0, 1, 3);
0077 
0078     //list of positions that we can use to provide useful autocompletion.
0079     d->positions << QString(i18nc("This is a list of suggestions for positions an artist can take, comma-separated","Adapter,Animator,Artist,Art Director,Author,Assistant,"
0080                                  "Editor,Background,Cartoonist,Colorist,Concept Artist,"
0081                                  "Corrector,Cover Artist,Creator,Designer,Inker,"
0082                                  "Letterer,Matte Painter,Painter,Penciller,Proofreader,"
0083                                  "Pixel Artist,Redliner,Sprite Artist,Typographer,Texture Artist,"
0084                                  "Translator,Writer,Other")).split(",");
0085 
0086     //Keep these two in sync!
0087     d->contactModes << i18n("Homepage") << i18n("Email") << i18n("Post Address") << i18n("Telephone") << i18n("Fax");
0088     d->contactKeys << "homepage" << "email" << "address" << "telephone" << "fax";
0089     QStringList headerlabels;
0090     headerlabels<< i18n("Type") << i18n("Entry");
0091 
0092     Ui::KoConfigAuthorPage *aUi = 0;
0093     QWidget *w = new QWidget;
0094     d->defaultAuthor = i18n("Anonymous");
0095 
0096     QStringList profilesNew;
0097     QDir dir(KoResourcePaths::getAppDataLocation() + "/authorinfo/");
0098     QStringList filters = QStringList() << "*.authorinfo";
0099     Q_FOREACH(const QString &entry, dir.entryList(filters)) {
0100         QFile file(dir.absoluteFilePath(entry));
0101         if (file.exists()) {
0102             file.open(QFile::ReadOnly);
0103             QByteArray ba = file.readAll();
0104             file.close();
0105             QDomDocument doc = QDomDocument();
0106             doc.setContent(ba);
0107             QDomElement root = doc.firstChildElement();
0108             aUi = new Ui::KoConfigAuthorPage();
0109             w = new QWidget;
0110             aUi->setupUi(w);
0111             QString profile = root.attribute("name");
0112 
0113             QDomElement el = root.firstChildElement("nickname");
0114             if (!el.isNull()) {
0115                 aUi->leNickName->setText(el.text());
0116             }
0117             el = root.firstChildElement("givenname");
0118             if (!el.isNull()) {
0119                 aUi->leFirstName->setText(el.text());
0120             }
0121             el = root.firstChildElement("middlename");
0122             if (!el.isNull()) {
0123                 aUi->leInitials->setText(el.text());
0124             }
0125             el = root.firstChildElement("familyname");
0126             if (!el.isNull()) {
0127                 aUi->leLastName->setText(el.text());
0128             }
0129             el = root.firstChildElement("title");
0130             if (!el.isNull()) {
0131                 aUi->leTitle->setText(el.text());
0132             }
0133             el = root.firstChildElement("position");
0134             if (!el.isNull()) {
0135                 aUi->lePosition->setText(el.text());
0136             }
0137             el = root.firstChildElement("company");
0138             if (!el.isNull()) {
0139                 aUi->leCompany->setText(el.text());
0140             }
0141 
0142             aUi->tblContactInfo->setItemDelegate(new KoContactInfoDelegate(this, d->contactModes));
0143             QStandardItemModel *modes = new QStandardItemModel();
0144             aUi->tblContactInfo->setModel(modes);
0145             el = root.firstChildElement("contact");
0146             while (!el.isNull()) {
0147                 QList<QStandardItem *> list;
0148                 QString type = d->contactModes.at(d->contactKeys.indexOf(el.attribute("type")));
0149                 list.append(new QStandardItem(type));
0150                 list.append(new QStandardItem(el.text()));
0151                 modes->appendRow(list);
0152                 el = el.nextSiblingElement("contact");
0153             }
0154             modes->setHorizontalHeaderLabels(headerlabels);
0155             QCompleter *positionSuggestions = new QCompleter(d->positions);
0156             positionSuggestions->setCaseSensitivity(Qt::CaseInsensitive);
0157             aUi->lePosition->setCompleter(positionSuggestions);
0158 
0159             connect(aUi->btnAdd, SIGNAL(clicked()), this, SLOT(addContactEntry()));
0160             connect(aUi->btnRemove, SIGNAL(clicked()), this, SLOT(removeContactEntry()));
0161 
0162             d->cmbAuthorProfiles->addItem(profile);
0163             profilesNew.append(profile);
0164             d->profileUiList.append(aUi);
0165             d->stack->addWidget(w);
0166         }
0167     }
0168 
0169     // Add all the user defined profiles (old type)
0170     KConfigGroup authorGroup(KSharedConfig::openConfig(), "Author");
0171     QStringList profiles = authorGroup.readEntry("profile-names", QStringList());
0172 
0173 
0174     foreach (const QString &profile , profiles) {
0175         if (!profilesNew.contains(profile)) {
0176             KConfigGroup cgs(&authorGroup, "Author-" + profile);
0177             aUi = new Ui::KoConfigAuthorPage();
0178             w = new QWidget;
0179             aUi->setupUi(w);
0180             aUi->leNickName->setText(cgs.readEntry("creator"));
0181             aUi->leFirstName->setText(cgs.readEntry("creator-first-name"));
0182             aUi->leLastName->setText(cgs.readEntry("creator-last-name"));
0183             aUi->leInitials->setText(cgs.readEntry("initial"));
0184             aUi->leTitle->setText(cgs.readEntry("author-title"));
0185             aUi->lePosition->setText(cgs.readEntry("position"));
0186             QCompleter *positionSuggestions = new QCompleter(d->positions);
0187             positionSuggestions->setCaseSensitivity(Qt::CaseInsensitive);
0188             aUi->lePosition->setCompleter(positionSuggestions);
0189             aUi->leCompany->setText(cgs.readEntry("company"));
0190 
0191             aUi->tblContactInfo->setItemDelegate(new KoContactInfoDelegate(this, d->contactModes));
0192             QStandardItemModel *modes = new QStandardItemModel();
0193             aUi->tblContactInfo->setModel(modes);
0194             if (cgs.hasKey("email")) {
0195                 QList<QStandardItem *> list;
0196                 QString email = d->contactModes.at(d->contactKeys.indexOf("email"));
0197                 list.append(new QStandardItem(email));
0198                 list.append(new QStandardItem(cgs.readEntry("email")));
0199                 modes->appendRow(list);
0200             }
0201             if (cgs.hasKey("telephone-work")) {
0202                 QList<QStandardItem *> list;
0203                 QString tel = d->contactModes.at(d->contactKeys.indexOf("telephone"));
0204                 list.append(new QStandardItem(tel));
0205                 list.append(new QStandardItem(cgs.readEntry("telephone-work")));
0206                 modes->appendRow(list);
0207             }
0208             if (cgs.hasKey("fax")) {
0209                 QList<QStandardItem *> list;
0210                 QString fax = d->contactModes.at(d->contactKeys.indexOf("fax"));
0211                 list.append(new QStandardItem(fax));
0212                 list.append(new QStandardItem(cgs.readEntry("fax")));
0213                 modes->appendRow(list);
0214             }
0215             QStringList postal;
0216             postal << cgs.readEntry("street") << cgs.readEntry("postal-code") << cgs.readEntry("city") << cgs.readEntry("country");
0217             QString address;
0218             Q_FOREACH(QString part, postal) {
0219                 if (!part.isEmpty()) {
0220                     address+= part + "\n";
0221                 }
0222             }
0223             if (!address.isEmpty()) {
0224                 QList<QStandardItem *> list;
0225                 QString add = d->contactModes.at(d->contactKeys.indexOf("address"));
0226                 list.append(new QStandardItem(add));
0227                 list.append(new QStandardItem(address));
0228                 modes->appendRow(list);
0229             }
0230             modes->setHorizontalHeaderLabels(headerlabels);
0231             connect(aUi->btnAdd, SIGNAL(clicked()), this, SLOT(addContactEntry()));
0232             connect(aUi->btnRemove, SIGNAL(clicked()), this, SLOT(removeContactEntry()));
0233 
0234             d->cmbAuthorProfiles->addItem(profile);
0235             d->profileUiList.append(aUi);
0236             d->stack->addWidget(w);
0237         }
0238     }
0239 
0240 
0241     // Add a default profile
0242     aUi = new Ui::KoConfigAuthorPage();
0243     w = new QWidget;
0244     if (!profiles.contains(d->defaultAuthor) || profilesNew.contains(d->defaultAuthor)) {
0245         //w->setEnabled(false);
0246         aUi->setupUi(w);
0247         w->setEnabled(false);
0248         d->cmbAuthorProfiles->insertItem(0, d->defaultAuthor);
0249         d->stack->insertWidget(0, w);
0250         d->profileUiList.insert(0, aUi);
0251     } else {
0252         delete aUi;
0253         delete w;
0254     }
0255 
0256 
0257     // Connect slots
0258     connect(d->cmbAuthorProfiles, SIGNAL(currentIndexChanged(int)), this, SLOT(profileChanged(int)));
0259     connect(newUser, SIGNAL(clicked(bool)), this, SLOT(addUser()));
0260     connect(d->bnDeleteUser, SIGNAL(clicked(bool)), this, SLOT(deleteUser()));
0261 
0262     d->cmbAuthorProfiles->setCurrentIndex(0);
0263     profileChanged(0);
0264 }
0265 
0266 KoConfigAuthorPage::~KoConfigAuthorPage()
0267 {
0268     delete d;
0269 }
0270 
0271 void KoConfigAuthorPage::profileChanged(int i)
0272 {
0273     d->stack->setCurrentIndex(i);
0274     // Profile 0 should never be deleted: it's the anonymous profile.
0275     d->bnDeleteUser->setEnabled(i > 0);
0276 }
0277 
0278 void KoConfigAuthorPage::addUser()
0279 {
0280     bool ok;
0281     QString profileName = QInputDialog::getText(this, i18n("Name of Profile"), i18n("Name (not duplicate or blank name):"), QLineEdit::Normal, "", &ok);
0282 
0283     if (!ok) {
0284         return;
0285     }
0286 
0287     Ui::KoConfigAuthorPage *curUi = d->profileUiList[d->cmbAuthorProfiles->currentIndex()];
0288     Ui::KoConfigAuthorPage *aUi = new Ui::KoConfigAuthorPage();
0289     QWidget *w = new QWidget;
0290     aUi->setupUi(w);
0291 
0292     aUi->leNickName->setText(curUi->leNickName->text());
0293     aUi->leInitials->setText(curUi->leInitials->text());
0294     aUi->leTitle->setText(curUi->leTitle->text());
0295     aUi->leCompany->setText(curUi->leCompany->text());
0296     aUi->leFirstName->setText(curUi->leFirstName->text());
0297     aUi->leLastName->setText(curUi->leLastName->text());
0298     aUi->lePosition->setText(curUi->lePosition->text());
0299     QCompleter *positionSuggestions = new QCompleter(d->positions);
0300     positionSuggestions->setCaseSensitivity(Qt::CaseInsensitive);
0301     aUi->lePosition->setCompleter(positionSuggestions);
0302     aUi->tblContactInfo->setItemDelegate(new KoContactInfoDelegate(this, d->contactModes));
0303     QStandardItemModel *modes = new QStandardItemModel();
0304     aUi->tblContactInfo->setModel(modes);
0305 
0306     connect(aUi->btnAdd, SIGNAL(clicked()), this, SLOT(addContactEntry()));
0307     connect(aUi->btnRemove, SIGNAL(clicked()), this, SLOT(removeContactEntry()));
0308 
0309     int index = d->cmbAuthorProfiles->currentIndex() + 1;
0310     d->cmbAuthorProfiles->insertItem(index, profileName);
0311     d->profileUiList.insert(index, aUi);
0312     d->stack->insertWidget(index, w);
0313     d->cmbAuthorProfiles->setCurrentIndex(index);
0314 }
0315 
0316 void KoConfigAuthorPage::deleteUser()
0317 {
0318     int index = d->cmbAuthorProfiles->currentIndex();
0319     QWidget *w = d->stack->currentWidget();
0320 
0321     d->stack->removeWidget(w);
0322     d->profileUiList.removeAt(index);
0323     d->cmbAuthorProfiles->removeItem(index);
0324     delete w;
0325 }
0326 
0327 void KoConfigAuthorPage::addContactEntry()
0328 {
0329     int i = d->cmbAuthorProfiles->currentIndex();
0330     Ui::KoConfigAuthorPage *aUi = d->profileUiList[i];
0331     QStandardItemModel *contact = static_cast<QStandardItemModel*>(aUi->tblContactInfo->model());
0332     QList<QStandardItem*>list;
0333     list.append(new QStandardItem(d->contactModes.at(0)));
0334     list.append(new QStandardItem(i18n("New Contact Info")));
0335     contact->appendRow(list);
0336     aUi->tblContactInfo->setModel(contact);
0337 }
0338 
0339 void KoConfigAuthorPage::removeContactEntry()
0340 {
0341     int i = d->cmbAuthorProfiles->currentIndex();
0342     Ui::KoConfigAuthorPage *aUi = d->profileUiList[i];
0343     QModelIndex index = aUi->tblContactInfo->selectionModel()->currentIndex();
0344     aUi->tblContactInfo->model()->removeRow(index.row());
0345 }
0346 
0347 void KoConfigAuthorPage::apply()
0348 {
0349     QString authorInfo = KoResourcePaths::getAppDataLocation() + "/authorinfo/";
0350     QDir dir(authorInfo);
0351     if (!dir.mkpath(authorInfo)) {
0352         qWarning()<<"We can't make an author info directory, and therefore not save!";
0353         return;
0354     }
0355     for (int i = 0; i < d->profileUiList.size(); i++) {
0356         if (d->cmbAuthorProfiles->itemText(i)!= d->defaultAuthor) {
0357             QByteArray ba;
0358             QDomDocument doc = QDomDocument();
0359             Ui::KoConfigAuthorPage *aUi = d->profileUiList[i];
0360 
0361             QDomElement root = doc.createElement("author");
0362             root.setAttribute("name", d->cmbAuthorProfiles->itemText(i));
0363 
0364             QDomElement nickname = doc.createElement("nickname");
0365             nickname.appendChild(doc.createTextNode(aUi->leNickName->text()));
0366             root.appendChild(nickname);
0367             QDomElement givenname = doc.createElement("givenname");
0368             givenname.appendChild(doc.createTextNode(aUi->leFirstName->text()));
0369             root.appendChild(givenname);
0370             QDomElement familyname = doc.createElement("familyname");
0371             familyname.appendChild(doc.createTextNode(aUi->leLastName->text()));
0372             root.appendChild(familyname);
0373             QDomElement middlename = doc.createElement("middlename");
0374             middlename.appendChild(doc.createTextNode(aUi->leInitials->text()));
0375             root.appendChild(middlename);
0376             QDomElement title = doc.createElement("title");
0377             title.appendChild(doc.createTextNode(aUi->leTitle->text()));
0378             root.appendChild(title);
0379             QDomElement company = doc.createElement("company");
0380             company.appendChild(doc.createTextNode(aUi->leCompany->text()));
0381             root.appendChild(company);
0382             QDomElement position = doc.createElement("position");
0383             position.appendChild(doc.createTextNode(aUi->lePosition->text()));
0384             root.appendChild(position);
0385             if (aUi->tblContactInfo) {
0386                 if (aUi->tblContactInfo->model()) {
0387                     for (int i=0; i<aUi->tblContactInfo->model()->rowCount(); i++) {
0388                         QModelIndex index = aUi->tblContactInfo->model()->index(i, 1);
0389                         QModelIndex typeIndex = aUi->tblContactInfo->model()->index(i, 0);
0390                         QDomElement contactEl = doc.createElement("contact");
0391                         QString content = QVariant(aUi->tblContactInfo->model()->data(index)).toString();
0392                         contactEl.appendChild(doc.createTextNode(content));
0393                         QString type = QVariant(aUi->tblContactInfo->model()->data(typeIndex)).toString();
0394                         contactEl.setAttribute("type", d->contactKeys.at(d->contactModes.indexOf(type)));
0395                         root.appendChild(contactEl);
0396                     }
0397                 }
0398             }
0399             doc.appendChild(root);
0400             ba = doc.toByteArray();
0401 
0402             QFile f(authorInfo + d->cmbAuthorProfiles->itemText(i) +".authorinfo");
0403             f.open(QFile::WriteOnly);
0404             if (f.write(ba) < 0) {
0405                 qWarning()<<"Writing author info went wrong:"<<f.errorString();
0406             }
0407             f.close();
0408         }
0409     }
0410 }
0411 
0412 KoContactInfoDelegate::KoContactInfoDelegate(QWidget *parent, QStringList contactModes): QStyledItemDelegate(parent), m_contactModes(contactModes)
0413 {
0414 }
0415 
0416 KoContactInfoDelegate::~KoContactInfoDelegate()
0417 {
0418 
0419 }
0420 
0421 QWidget* KoContactInfoDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &index) const
0422 {
0423 
0424     if (index.column() > 0) {
0425         return new QLineEdit(parent);
0426     } else {
0427         QComboBox *box = new QComboBox(parent);
0428         box->addItems(m_contactModes);
0429         return box;
0430     }
0431 }