File indexing completed on 2024-05-12 16:02:08

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     }
0252 
0253 
0254     // Connect slots
0255     connect(d->cmbAuthorProfiles, SIGNAL(currentIndexChanged(int)), this, SLOT(profileChanged(int)));
0256     connect(newUser, SIGNAL(clicked(bool)), this, SLOT(addUser()));
0257     connect(d->bnDeleteUser, SIGNAL(clicked(bool)), this, SLOT(deleteUser()));
0258 
0259     d->cmbAuthorProfiles->setCurrentIndex(0);
0260     profileChanged(0);
0261 }
0262 
0263 KoConfigAuthorPage::~KoConfigAuthorPage()
0264 {
0265     delete d;
0266 }
0267 
0268 void KoConfigAuthorPage::profileChanged(int i)
0269 {
0270     d->stack->setCurrentIndex(i);
0271     // Profile 0 should never be deleted: it's the anonymous profile.
0272     d->bnDeleteUser->setEnabled(i > 0);
0273 }
0274 
0275 void KoConfigAuthorPage::addUser()
0276 {
0277     bool ok;
0278     QString profileName = QInputDialog::getText(this, i18n("Name of Profile"), i18n("Name (not duplicate or blank name):"), QLineEdit::Normal, "", &ok);
0279 
0280     if (!ok) {
0281         return;
0282     }
0283 
0284     Ui::KoConfigAuthorPage *curUi = d->profileUiList[d->cmbAuthorProfiles->currentIndex()];
0285     Ui::KoConfigAuthorPage *aUi = new Ui::KoConfigAuthorPage();
0286     QWidget *w = new QWidget;
0287     aUi->setupUi(w);
0288 
0289     aUi->leNickName->setText(curUi->leNickName->text());
0290     aUi->leInitials->setText(curUi->leInitials->text());
0291     aUi->leTitle->setText(curUi->leTitle->text());
0292     aUi->leCompany->setText(curUi->leCompany->text());
0293     aUi->leFirstName->setText(curUi->leFirstName->text());
0294     aUi->leLastName->setText(curUi->leLastName->text());
0295     aUi->lePosition->setText(curUi->lePosition->text());
0296     QCompleter *positionSuggestions = new QCompleter(d->positions);
0297     positionSuggestions->setCaseSensitivity(Qt::CaseInsensitive);
0298     aUi->lePosition->setCompleter(positionSuggestions);
0299     aUi->tblContactInfo->setItemDelegate(new KoContactInfoDelegate(this, d->contactModes));
0300     QStandardItemModel *modes = new QStandardItemModel();
0301     aUi->tblContactInfo->setModel(modes);
0302 
0303     connect(aUi->btnAdd, SIGNAL(clicked()), this, SLOT(addContactEntry()));
0304     connect(aUi->btnRemove, SIGNAL(clicked()), this, SLOT(removeContactEntry()));
0305 
0306     int index = d->cmbAuthorProfiles->currentIndex() + 1;
0307     d->cmbAuthorProfiles->insertItem(index, profileName);
0308     d->profileUiList.insert(index, aUi);
0309     d->stack->insertWidget(index, w);
0310     d->cmbAuthorProfiles->setCurrentIndex(index);
0311 }
0312 
0313 void KoConfigAuthorPage::deleteUser()
0314 {
0315     int index = d->cmbAuthorProfiles->currentIndex();
0316     QWidget *w = d->stack->currentWidget();
0317 
0318     d->stack->removeWidget(w);
0319     d->profileUiList.removeAt(index);
0320     d->cmbAuthorProfiles->removeItem(index);
0321     delete w;
0322 }
0323 
0324 void KoConfigAuthorPage::addContactEntry()
0325 {
0326     int i = d->cmbAuthorProfiles->currentIndex();
0327     Ui::KoConfigAuthorPage *aUi = d->profileUiList[i];
0328     QStandardItemModel *contact = static_cast<QStandardItemModel*>(aUi->tblContactInfo->model());
0329     QList<QStandardItem*>list;
0330     list.append(new QStandardItem(d->contactModes.at(0)));
0331     list.append(new QStandardItem(i18n("New Contact Info")));
0332     contact->appendRow(list);
0333     aUi->tblContactInfo->setModel(contact);
0334 }
0335 
0336 void KoConfigAuthorPage::removeContactEntry()
0337 {
0338     int i = d->cmbAuthorProfiles->currentIndex();
0339     Ui::KoConfigAuthorPage *aUi = d->profileUiList[i];
0340     QModelIndex index = aUi->tblContactInfo->selectionModel()->currentIndex();
0341     aUi->tblContactInfo->model()->removeRow(index.row());
0342 }
0343 
0344 void KoConfigAuthorPage::apply()
0345 {
0346     QString authorInfo = KoResourcePaths::getAppDataLocation() + "/authorinfo/";
0347     QDir dir(authorInfo);
0348     if (!dir.mkpath(authorInfo)) {
0349         qWarning()<<"We can't make an author info directory, and therefore not save!";
0350         return;
0351     }
0352     for (int i = 0; i < d->profileUiList.size(); i++) {
0353         if (d->cmbAuthorProfiles->itemText(i)!= d->defaultAuthor) {
0354             QByteArray ba;
0355             QDomDocument doc = QDomDocument();
0356             Ui::KoConfigAuthorPage *aUi = d->profileUiList[i];
0357 
0358             QDomElement root = doc.createElement("author");
0359             root.setAttribute("name", d->cmbAuthorProfiles->itemText(i));
0360 
0361             QDomElement nickname = doc.createElement("nickname");
0362             nickname.appendChild(doc.createTextNode(aUi->leNickName->text()));
0363             root.appendChild(nickname);
0364             QDomElement givenname = doc.createElement("givenname");
0365             givenname.appendChild(doc.createTextNode(aUi->leFirstName->text()));
0366             root.appendChild(givenname);
0367             QDomElement familyname = doc.createElement("familyname");
0368             familyname.appendChild(doc.createTextNode(aUi->leLastName->text()));
0369             root.appendChild(familyname);
0370             QDomElement middlename = doc.createElement("middlename");
0371             middlename.appendChild(doc.createTextNode(aUi->leInitials->text()));
0372             root.appendChild(middlename);
0373             QDomElement title = doc.createElement("title");
0374             title.appendChild(doc.createTextNode(aUi->leTitle->text()));
0375             root.appendChild(title);
0376             QDomElement company = doc.createElement("company");
0377             company.appendChild(doc.createTextNode(aUi->leCompany->text()));
0378             root.appendChild(company);
0379             QDomElement position = doc.createElement("position");
0380             position.appendChild(doc.createTextNode(aUi->lePosition->text()));
0381             root.appendChild(position);
0382             if (aUi->tblContactInfo) {
0383                 if (aUi->tblContactInfo->model()) {
0384                     for (int i=0; i<aUi->tblContactInfo->model()->rowCount(); i++) {
0385                         QModelIndex index = aUi->tblContactInfo->model()->index(i, 1);
0386                         QModelIndex typeIndex = aUi->tblContactInfo->model()->index(i, 0);
0387                         QDomElement contactEl = doc.createElement("contact");
0388                         QString content = QVariant(aUi->tblContactInfo->model()->data(index)).toString();
0389                         contactEl.appendChild(doc.createTextNode(content));
0390                         QString type = QVariant(aUi->tblContactInfo->model()->data(typeIndex)).toString();
0391                         contactEl.setAttribute("type", d->contactKeys.at(d->contactModes.indexOf(type)));
0392                         root.appendChild(contactEl);
0393                     }
0394                 }
0395             }
0396             doc.appendChild(root);
0397             ba = doc.toByteArray();
0398 
0399             QFile f(authorInfo + d->cmbAuthorProfiles->itemText(i) +".authorinfo");
0400             f.open(QFile::WriteOnly);
0401             if (f.write(ba) < 0) {
0402                 qWarning()<<"Writing author info went wrong:"<<f.errorString();
0403             }
0404             f.close();
0405         }
0406     }
0407 }
0408 
0409 KoContactInfoDelegate::KoContactInfoDelegate(QWidget *parent, QStringList contactModes): QStyledItemDelegate(parent), m_contactModes(contactModes)
0410 {
0411 }
0412 
0413 KoContactInfoDelegate::~KoContactInfoDelegate()
0414 {
0415 
0416 }
0417 
0418 QWidget* KoContactInfoDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &index) const
0419 {
0420 
0421     if (index.column() > 0) {
0422         return new QLineEdit(parent);
0423     } else {
0424         QComboBox *box = new QComboBox(parent);
0425         box->addItems(m_contactModes);
0426         return box;
0427     }
0428 }