File indexing completed on 2024-06-16 05:00:38

0001 /*
0002    SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "selectiontypetreewidget.h"
0008 #include "core/utils.h"
0009 #include "core/xml/templateselection.h"
0010 
0011 #include <PimCommon/PimUtil>
0012 
0013 #include <QFileDialog>
0014 
0015 #include <KLocalizedString>
0016 #include <QTemporaryFile>
0017 
0018 #include <QHeaderView>
0019 #include <QPointer>
0020 #include <QTreeWidgetItem>
0021 
0022 SelectionTypeTreeWidget::SelectionTypeTreeWidget(bool backupData, QWidget *parent)
0023     : QTreeWidget(parent)
0024 {
0025     initialize(backupData);
0026     expandAll();
0027     header()->hide();
0028 }
0029 
0030 SelectionTypeTreeWidget::~SelectionTypeTreeWidget() = default;
0031 
0032 void SelectionTypeTreeWidget::initialize(bool backupData)
0033 {
0034     mKmailItem = new QTreeWidgetItem(this);
0035     mKmailItem->setCheckState(0, Qt::Checked);
0036     mKmailItem->setText(0, Utils::appTypeToI18n(Utils::KMail));
0037     createSubItem(mKmailItem, Utils::Identity);
0038     createSubItem(mKmailItem, Utils::Mails);
0039     createSubItem(mKmailItem, Utils::MailTransport);
0040     createSubItem(mKmailItem, Utils::Resources);
0041     createSubItem(mKmailItem, Utils::Config);
0042 
0043     mKaddressbookItem = new QTreeWidgetItem(this);
0044     mKaddressbookItem->setText(0, Utils::appTypeToI18n(Utils::KAddressBook));
0045     mKaddressbookItem->setCheckState(0, Qt::Checked);
0046     createSubItem(mKaddressbookItem, Utils::Resources);
0047     createSubItem(mKaddressbookItem, Utils::Config);
0048 
0049     mKalarmItem = new QTreeWidgetItem(this);
0050     mKalarmItem->setText(0, Utils::appTypeToI18n(Utils::KAlarm));
0051     mKalarmItem->setCheckState(0, Qt::Checked);
0052     createSubItem(mKalarmItem, Utils::Resources);
0053     createSubItem(mKalarmItem, Utils::Config);
0054 
0055     mKorganizerItem = new QTreeWidgetItem(this);
0056     mKorganizerItem->setText(0, Utils::appTypeToI18n(Utils::KOrganizer));
0057     mKorganizerItem->setCheckState(0, Qt::Checked);
0058     createSubItem(mKorganizerItem, Utils::Resources);
0059     createSubItem(mKorganizerItem, Utils::Config);
0060 
0061     mKNotesItem = new QTreeWidgetItem(this);
0062     mKNotesItem->setText(0, Utils::appTypeToI18n(Utils::KNotes));
0063     mKNotesItem->setCheckState(0, Qt::Checked);
0064     createSubItem(mKNotesItem, Utils::Resources);
0065     createSubItem(mKNotesItem, Utils::Config);
0066     if (!backupData) {
0067         createSubItem(mKNotesItem, Utils::Data);
0068     }
0069 
0070     mAkregatorItem = new QTreeWidgetItem(this);
0071     mAkregatorItem->setText(0, Utils::appTypeToI18n(Utils::Akregator));
0072     mAkregatorItem->setCheckState(0, Qt::Checked);
0073     createSubItem(mAkregatorItem, Utils::Config);
0074     createSubItem(mAkregatorItem, Utils::Data);
0075 
0076     connect(this, &SelectionTypeTreeWidget::itemChanged, this, &SelectionTypeTreeWidget::slotItemChanged);
0077 }
0078 
0079 void SelectionTypeTreeWidget::removeNotSelectedItems()
0080 {
0081     if (!removeNotSelectedItem(mKmailItem)) {
0082         delete mKmailItem;
0083         mKmailItem = nullptr;
0084     }
0085     if (!removeNotSelectedItem(mKalarmItem)) {
0086         delete mKalarmItem;
0087         mKalarmItem = nullptr;
0088     }
0089     if (!removeNotSelectedItem(mKaddressbookItem)) {
0090         delete mKaddressbookItem;
0091         mKaddressbookItem = nullptr;
0092     }
0093     if (!removeNotSelectedItem(mKorganizerItem)) {
0094         delete mKorganizerItem;
0095         mKorganizerItem = nullptr;
0096     }
0097     if (!removeNotSelectedItem(mKNotesItem)) {
0098         delete mKNotesItem;
0099         mKNotesItem = nullptr;
0100     }
0101     if (!removeNotSelectedItem(mAkregatorItem)) {
0102         delete mAkregatorItem;
0103         mAkregatorItem = nullptr;
0104     }
0105 }
0106 
0107 bool SelectionTypeTreeWidget::removeNotSelectedItem(QTreeWidgetItem *parent)
0108 {
0109     for (int i = parent->childCount() - 1; i >= 0; --i) {
0110         QTreeWidgetItem *item = parent->child(i);
0111         if (item->checkState(0) == Qt::Unchecked) {
0112             delete item;
0113         }
0114     }
0115     bool hasChildren = (parent->childCount() != 0);
0116     if (hasChildren) {
0117         parent->setCheckState(0, Qt::Checked);
0118     }
0119     return hasChildren;
0120 }
0121 
0122 QMap<Utils::AppsType, Utils::importExportParameters> SelectionTypeTreeWidget::storedType() const
0123 {
0124     QMap<Utils::AppsType, Utils::importExportParameters> stored;
0125     Utils::importExportParameters var = typeChecked(mKmailItem);
0126     if (!var.isEmpty()) {
0127         stored.insert(Utils::KMail, var);
0128     }
0129     var = typeChecked(mKalarmItem);
0130     if (!var.isEmpty()) {
0131         stored.insert(Utils::KAlarm, var);
0132     }
0133     var = typeChecked(mKaddressbookItem);
0134     if (!var.isEmpty()) {
0135         stored.insert(Utils::KAddressBook, var);
0136     }
0137     var = typeChecked(mKorganizerItem);
0138     if (!var.isEmpty()) {
0139         stored.insert(Utils::KOrganizer, var);
0140     }
0141     var = typeChecked(mKNotesItem);
0142     if (!var.isEmpty()) {
0143         stored.insert(Utils::KNotes, var);
0144     }
0145     var = typeChecked(mAkregatorItem);
0146     if (!var.isEmpty()) {
0147         stored.insert(Utils::Akregator, var);
0148     }
0149     return stored;
0150 }
0151 
0152 Utils::importExportParameters SelectionTypeTreeWidget::typeChecked(QTreeWidgetItem *parent) const
0153 {
0154     Utils::importExportParameters parameters;
0155     if (parent) {
0156         int numberOfStep = 0;
0157         Utils::StoredTypes types = Utils::None;
0158         for (int i = 0; i < parent->childCount(); ++i) {
0159             QTreeWidgetItem *item = parent->child(i);
0160             if (item->checkState(0) == Qt::Checked) {
0161                 types |= static_cast<Utils::StoredType>(item->data(0, action).toInt());
0162                 ++numberOfStep;
0163             }
0164         }
0165         parameters.types = types;
0166         parameters.numberSteps = numberOfStep;
0167     }
0168     return parameters;
0169 }
0170 
0171 void SelectionTypeTreeWidget::createSubItem(QTreeWidgetItem *parent, Utils::StoredType type)
0172 {
0173     switch (type) {
0174     case Utils::None:
0175         break;
0176     case Utils::Identity: {
0177         auto item = new QTreeWidgetItem(parent);
0178         item->setText(0, Utils::storedTypeToI18n(Utils::Identity));
0179         item->setCheckState(0, Qt::Checked);
0180         item->setData(0, action, type);
0181         break;
0182     }
0183     case Utils::Mails: {
0184         auto item = new QTreeWidgetItem(parent);
0185         item->setText(0, Utils::storedTypeToI18n(Utils::Mails));
0186         item->setCheckState(0, Qt::Checked);
0187         item->setData(0, action, type);
0188         break;
0189     }
0190     case Utils::MailTransport: {
0191         auto item = new QTreeWidgetItem(parent);
0192         item->setText(0, Utils::storedTypeToI18n(Utils::MailTransport));
0193         item->setCheckState(0, Qt::Checked);
0194         item->setData(0, action, type);
0195         break;
0196     }
0197     case Utils::Resources: {
0198         auto item = new QTreeWidgetItem(parent);
0199         item->setText(0, Utils::storedTypeToI18n(Utils::Resources));
0200         item->setCheckState(0, Qt::Checked);
0201         item->setData(0, action, type);
0202         break;
0203     }
0204     case Utils::Config: {
0205         auto item = new QTreeWidgetItem(parent);
0206         item->setText(0, Utils::storedTypeToI18n(Utils::Config));
0207         item->setCheckState(0, Qt::Checked);
0208         item->setData(0, action, type);
0209         break;
0210     }
0211     case Utils::Data: {
0212         auto item = new QTreeWidgetItem(parent);
0213         item->setText(0, Utils::storedTypeToI18n(Utils::Data));
0214         item->setCheckState(0, Qt::Checked);
0215         item->setData(0, action, type);
0216         break;
0217     }
0218     }
0219 }
0220 
0221 void SelectionTypeTreeWidget::selectAllItems()
0222 {
0223     setSelectItems(true);
0224 }
0225 
0226 void SelectionTypeTreeWidget::unSelectAllItems()
0227 {
0228     setSelectItems(false);
0229 }
0230 
0231 void SelectionTypeTreeWidget::setSelectItems(bool b)
0232 {
0233     changeState(mKmailItem, b);
0234     changeState(mKalarmItem, b);
0235     changeState(mKaddressbookItem, b);
0236     changeState(mKorganizerItem, b);
0237     changeState(mKNotesItem, b);
0238     changeState(mAkregatorItem, b);
0239 }
0240 
0241 void SelectionTypeTreeWidget::changeState(QTreeWidgetItem *item, bool b)
0242 {
0243     if (item) {
0244         blockSignals(true);
0245         item->setCheckState(0, b ? Qt::Checked : Qt::Unchecked);
0246         for (int i = 0; i < item->childCount(); ++i) {
0247             item->child(i)->setCheckState(0, b ? Qt::Checked : Qt::Unchecked);
0248         }
0249         blockSignals(false);
0250     }
0251 }
0252 
0253 void SelectionTypeTreeWidget::slotItemChanged(QTreeWidgetItem *item, int column)
0254 {
0255     if (column != 0) {
0256         return;
0257     }
0258     // Parent
0259     if (item->childCount() != 0) {
0260         changeState(item, item->checkState(0) == Qt::Checked);
0261     } else { // child
0262         blockSignals(true);
0263         QTreeWidgetItem *parent = item->parent();
0264         Qt::CheckState state = Qt::PartiallyChecked;
0265         for (int i = 0; i < parent->childCount(); ++i) {
0266             if (i == 0) {
0267                 state = parent->child(i)->checkState(0);
0268             } else {
0269                 if (state != parent->child(i)->checkState(0)) {
0270                     state = Qt::PartiallyChecked;
0271                     break;
0272                 }
0273             }
0274         }
0275         parent->setCheckState(0, state);
0276         blockSignals(false);
0277     }
0278 }
0279 
0280 void SelectionTypeTreeWidget::loadFileName(const QString &fileName)
0281 {
0282     unSelectAllItems();
0283     TemplateSelection templateSelection;
0284     const QMap<Utils::AppsType, Utils::importExportParameters> params = templateSelection.loadTemplate(fileName);
0285     setParameters(params);
0286 }
0287 
0288 void SelectionTypeTreeWidget::loadDefaultTemplate()
0289 {
0290     // Keep old name for compatibility
0291     QString ret = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("/pimsettingexporter/defaulttemplate.xml"));
0292     if (ret.isEmpty()) {
0293         ret = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("/pimdataexporter/defaulttemplate.xml"));
0294     }
0295     if (!ret.isEmpty()) {
0296         loadFileName(ret);
0297     }
0298 }
0299 
0300 void SelectionTypeTreeWidget::loadTemplate(const QString &fileName)
0301 {
0302     if (fileName.isEmpty()) {
0303         QPointer<QFileDialog> dlg = new QFileDialog(this, QString(), QString(), QStringLiteral("*.xml"));
0304         dlg->setFileMode(QFileDialog::ExistingFile);
0305         if (dlg->exec()) {
0306             const QStringList file = dlg->selectedFiles();
0307             loadFileName(file.at(0));
0308         }
0309         delete dlg;
0310     } else {
0311         loadFileName(fileName);
0312     }
0313 }
0314 
0315 QString SelectionTypeTreeWidget::exportedFileInfo()
0316 {
0317     const QString templateStr = templateSelectionToString();
0318     QTemporaryFile tmp;
0319     tmp.open();
0320     if (!PimCommon::Util::saveToFile(tmp.fileName(), templateStr)) {
0321         return {};
0322     } else {
0323         tmp.setAutoRemove(false);
0324     }
0325     return tmp.fileName();
0326 }
0327 
0328 QString SelectionTypeTreeWidget::templateSelectionToString()
0329 {
0330     TemplateSelection templateSelection;
0331     templateSelection.createTemplate(storedType());
0332     const QString templateStr = templateSelection.saveTemplate();
0333     return templateStr;
0334 }
0335 
0336 void SelectionTypeTreeWidget::saveAsDefaultTemplate()
0337 {
0338     const QString templateStr = templateSelectionToString();
0339     const QString ret = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/pimdataexporter/");
0340     QDir().mkpath(ret);
0341 
0342     if (!PimCommon::Util::saveToFile(ret + QStringLiteral("defaulttemplate.xml"), templateStr)) {
0343         qWarning() << "Impossible to save as defaulttemplate.xml";
0344     }
0345 }
0346 
0347 void SelectionTypeTreeWidget::saveAsTemplate()
0348 {
0349     const QString templateStr = templateSelectionToString();
0350     const QString filter(i18n("Template Files (*.xml)"));
0351     PimCommon::Util::saveTextAs(templateStr, filter, this);
0352 }
0353 
0354 void SelectionTypeTreeWidget::initializeSubItem(QTreeWidgetItem *item, Utils::StoredTypes types)
0355 {
0356     for (int i = 0; i < item->childCount(); ++i) {
0357         QTreeWidgetItem *child = item->child(i);
0358         if (types & static_cast<Utils::StoredType>(child->data(0, action).toInt())) {
0359             child->setCheckState(0, Qt::Checked);
0360         } else {
0361             child->setCheckState(0, Qt::Unchecked);
0362         }
0363     }
0364 }
0365 
0366 void SelectionTypeTreeWidget::setParameters(const QMap<Utils::AppsType, Utils::importExportParameters> &params)
0367 {
0368     QMap<Utils::AppsType, Utils::importExportParameters>::const_iterator i = params.constBegin();
0369     while (i != params.constEnd()) {
0370         switch (i.key()) {
0371         case Utils::KMail:
0372             initializeSubItem(mKmailItem, i.value().types);
0373             break;
0374         case Utils::KAddressBook:
0375             initializeSubItem(mKaddressbookItem, i.value().types);
0376             break;
0377         case Utils::KAlarm:
0378             initializeSubItem(mKalarmItem, i.value().types);
0379             break;
0380         case Utils::KOrganizer:
0381             initializeSubItem(mKorganizerItem, i.value().types);
0382             break;
0383         case Utils::KNotes:
0384             initializeSubItem(mKNotesItem, i.value().types);
0385             break;
0386         case Utils::Akregator:
0387             initializeSubItem(mAkregatorItem, i.value().types);
0388             break;
0389         case Utils::Unknown:
0390             break;
0391         }
0392         ++i;
0393     }
0394 }
0395 
0396 #include "moc_selectiontypetreewidget.cpp"